Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(621)

Side by Side Diff: chrome/browser/tab_restore_service.cc

Issue 11377: Changes tab restore service to handle restoring closed windows as a... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/tab_restore_service.h ('k') | chrome/browser/tab_restore_uitest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/tab_restore_service.h" 5 #include "chrome/browser/tab_restore_service.h"
6 6
7 #include "chrome/browser/profile.h" 7 #include "chrome/browser/browser_list.h"
8 #include "chrome/browser/navigation_controller.h" 8 #include "chrome/browser/navigation_controller.h"
9 #include "chrome/browser/navigation_entry.h" 9 #include "chrome/browser/navigation_entry.h"
10 #include "chrome/browser/profile.h"
11 #include "chrome/common/stl_util-inl.h"
10 12
11 using base::Time; 13 using base::Time;
12 14
13 // HistoricalTab -------------------------------------------------------------- 15 // Entry ----------------------------------------------------------------------
14 16
15 // ID of the next HistoricalTab. 17 // ID of the next Entry.
16 static int next_historical_tab_id = 1; 18 static int next_entry_id = 1;
17 19
18 TabRestoreService::HistoricalTab::HistoricalTab() 20 TabRestoreService::Entry::Entry() : id(next_entry_id++), type(TAB) {}
19 : close_time(Time::Now()), 21
20 from_last_session(false), 22 TabRestoreService::Entry::Entry(Type type) : id(next_entry_id++), type(type) {}
21 current_navigation_index(-1),
22 id(next_historical_tab_id++) {
23 }
24 23
25 // TabRestoreService ---------------------------------------------------------- 24 // TabRestoreService ----------------------------------------------------------
26 25
27 // Max number of tabs we'll keep around. 26 // Max number of entries we'll keep around.
28 static const size_t kMaxTabs = 10; 27 static const size_t kMaxEntries = 10;
29
30 // Amount of time from when the session starts and when we'll allow loading of
31 // the last sessions tabs.
32 static const int kLoadFromLastSessionMS = 600000;
33 28
34 TabRestoreService::TabRestoreService(Profile* profile) 29 TabRestoreService::TabRestoreService(Profile* profile)
35 : profile_(profile), 30 : profile_(profile),
36 loaded_last_session_(false) { 31 loaded_last_session_(false),
32 restoring_(false) {
37 } 33 }
38 34
39 TabRestoreService::~TabRestoreService() { 35 TabRestoreService::~TabRestoreService() {
40 FOR_EACH_OBSERVER(Observer, observer_list_, TabRestoreServiceDestroyed(this)); 36 FOR_EACH_OBSERVER(Observer, observer_list_, TabRestoreServiceDestroyed(this));
37 STLDeleteElements(&entries_);
41 } 38 }
42 39
43 void TabRestoreService::AddObserver(Observer* observer) { 40 void TabRestoreService::AddObserver(Observer* observer) {
44 observer_list_.AddObserver(observer); 41 observer_list_.AddObserver(observer);
45 } 42 }
46 43
47 void TabRestoreService::RemoveObserver(Observer* observer) { 44 void TabRestoreService::RemoveObserver(Observer* observer) {
48 observer_list_.RemoveObserver(observer); 45 observer_list_.RemoveObserver(observer);
49 } 46 }
50 47
51 void TabRestoreService::LoadPreviousSessionTabs() { 48 void TabRestoreService::CreateHistoricalTab(NavigationController* tab) {
52 if (!WillLoadPreviousSessionTabs() || IsLoadingPreviousSessionTabs()) 49 if (restoring_)
53 return; 50 return;
54 51
55 profile_->GetSessionService()->GetLastSession( 52 Browser* browser = Browser::GetBrowserForController(tab, NULL);
56 &cancelable_consumer_, 53 if (closing_browsers_.find(browser) != closing_browsers_.end())
57 NewCallback(this, &TabRestoreService::OnGotLastSession)); 54 return;
55
56 Tab* local_tab = new Tab();
57 PopulateTabFromController(tab, local_tab);
58 entries_.push_front(local_tab);
59
60 PruneAndNotify();
58 } 61 }
59 62
60 bool TabRestoreService::IsLoadingPreviousSessionTabs() { 63 void TabRestoreService::BrowserClosing(Browser* browser) {
61 return cancelable_consumer_.HasPendingRequests(); 64 if (browser->type() != Browser::TYPE_NORMAL ||
65 browser->tab_count() == 0)
66 return;
67
68 closing_browsers_.insert(browser);
69
70 Window* window = new Window();
71 window->selected_tab_index = browser->selected_index();
72 window->tabs.resize(browser->tab_count());
73 size_t entry_index = 0;
74 for (int tab_index = 0; tab_index < browser->tab_count(); ++tab_index) {
75 PopulateTabFromController(
76 browser->GetTabContentsAt(tab_index)->controller(),
77 &(window->tabs[entry_index]));
78 if (window->tabs[entry_index].navigations.empty())
79 window->tabs.erase(window->tabs.begin() + entry_index);
80 else
81 entry_index++;
82 }
83 if (window->tabs.empty()) {
84 delete window;
85 window = NULL;
86 } else {
87 entries_.push_front(window);
88 PruneAndNotify();
89 }
62 } 90 }
63 91
64 bool TabRestoreService::WillLoadPreviousSessionTabs() { 92 void TabRestoreService::BrowserClosed(Browser* browser) {
65 return (!loaded_last_session_ && tabs_.size() < kMaxTabs && 93 closing_browsers_.erase(browser);
66 (Time::Now() - profile_->GetStartTime()).InMilliseconds() <
67 kLoadFromLastSessionMS);
68 } 94 }
69 95
70 void TabRestoreService::CreateHistoricalTab(NavigationController* tab) { 96 void TabRestoreService::ClearEntries() {
71 tabs_.push_front(HistoricalTab()); 97 STLDeleteElements(&entries_);
72
73 PopulateTabFromController(tab, &(tabs_.front()));
74
75 while (tabs_.size() > kMaxTabs)
76 tabs_.pop_back();
77
78 NotifyTabsChanged(); 98 NotifyTabsChanged();
79 } 99 }
80 100
81 void TabRestoreService::RemoveHistoricalTabById(int id) { 101 void TabRestoreService::RestoreMostRecentEntry(Browser* browser) {
82 for (Tabs::iterator i = tabs_.begin(); i != tabs_.end(); ++i) { 102 if (entries_.empty())
83 if (i->id == id) { 103 return;
84 tabs_.erase(i); 104
85 NotifyTabsChanged(); 105 RestoreEntryById(browser, entries_.front()->id, false);
86 return;
87 }
88 }
89 // Don't hoark here, we allow an invalid id.
90 } 106 }
91 107
92 void TabRestoreService::ClearHistoricalTabs() { 108 void TabRestoreService::RestoreEntryById(Browser* browser,
93 tabs_.clear(); 109 int id,
94 NotifyTabsChanged(); 110 bool replace_existing_tab) {
95 } 111 Entries::iterator i = GetEntryIteratorById(id);
96 112 if (i == entries_.end()) {
97 void TabRestoreService::OnGotLastSession(SessionService::Handle handle, 113 // Don't hoark here, we allow an invalid id.
98 std::vector<SessionWindow*>* windows) {
99 DCHECK(!loaded_last_session_);
100 loaded_last_session_ = true;
101
102 if (tabs_.size() == kMaxTabs)
103 return; 114 return;
104
105 AddHistoricalTabs(windows);
106
107 NotifyTabsChanged();
108 }
109
110 void TabRestoreService::AddHistoricalTabs(
111 std::vector<SessionWindow*>* windows) {
112 // First pass, extract the selected tabs in each window.
113 for (size_t i = 0; i < windows->size(); ++i) {
114 SessionWindow* window = (*windows)[i];
115 if (window->type == Browser::TYPE_NORMAL) {
116 DCHECK(window->selected_tab_index >= 0 &&
117 window->selected_tab_index <
118 static_cast<int>(window->tabs.size()));
119 AppendHistoricalTabFromSessionTab(
120 window->tabs[window->selected_tab_index]);
121 if (tabs_.size() == kMaxTabs)
122 return;
123 }
124 } 115 }
125 116
126 // Second pass, extract the non-selected tabs. 117 restoring_ = true;
127 for (size_t window_index = 0; window_index < windows->size(); 118 Entry* entry = *i;
128 ++window_index) { 119 entries_.erase(i);
129 SessionWindow* window = (*windows)[window_index]; 120 i = entries_.end();
130 if (window->type != Browser::TYPE_NORMAL) 121 if (entry->type == TAB) {
131 continue; // Ignore popups. 122 Tab* tab = static_cast<Tab*>(entry);
132 123 if (replace_existing_tab) {
133 for (size_t tab_index = 0; tab_index < window->tabs.size(); ++tab_index) { 124 browser->ReplaceRestoredTab(tab->navigations,
134 if (tab_index == window->selected_tab_index) 125 tab->current_navigation_index);
135 continue; // Pass one took care of this tab. 126 } else {
136 AppendHistoricalTabFromSessionTab(window->tabs[tab_index]); 127 browser->AddRestoredTab(tab->navigations, browser->tab_count(),
137 if (tabs_.size() == kMaxTabs) 128 tab->current_navigation_index, true);
138 return;
139 } 129 }
130 } else if (entry->type == WINDOW) {
131 const Window* window = static_cast<Window*>(entry);
132 Browser* browser = Browser::Create(profile_);
133 for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) {
134 const Tab& tab = window->tabs[tab_i];
135 NavigationController* restored_controller =
136 browser->AddRestoredTab(tab.navigations, browser->tab_count(),
137 tab.current_navigation_index,
138 (tab_i == window->selected_tab_index));
139 if (restored_controller)
140 restored_controller->LoadIfNecessary();
141 }
142 browser->window()->Show();
143 } else {
144 NOTREACHED();
140 } 145 }
141 } 146 delete entry;
142 147 restoring_ = false;
143 void TabRestoreService::AppendHistoricalTabFromSessionTab( 148 NotifyTabsChanged();
144 SessionTab* tab) {
145 tabs_.push_back(HistoricalTab());
146 PopulateTabFromSessionTab(tab, &(tabs_.back()));
147 } 149 }
148 150
149 void TabRestoreService::PopulateTabFromController( 151 void TabRestoreService::PopulateTabFromController(
150 NavigationController* controller, 152 NavigationController* controller,
151 HistoricalTab* tab) { 153 Tab* tab) {
152 const int pending_index = controller->GetPendingEntryIndex(); 154 const int pending_index = controller->GetPendingEntryIndex();
153 int entry_count = controller->GetEntryCount(); 155 int entry_count = controller->GetEntryCount();
154 if (entry_count == 0 && pending_index == 0) 156 if (entry_count == 0 && pending_index == 0)
155 entry_count++; 157 entry_count++;
156 tab->navigations.resize(static_cast<int>(entry_count)); 158 tab->navigations.resize(static_cast<int>(entry_count));
157 for (int i = 0; i < entry_count; ++i) { 159 for (int i = 0; i < entry_count; ++i) {
158 NavigationEntry* entry = (i == pending_index) ? 160 NavigationEntry* entry = (i == pending_index) ?
159 controller->GetPendingEntry() : controller->GetEntryAtIndex(i); 161 controller->GetPendingEntry() : controller->GetEntryAtIndex(i);
160 TabNavigation& tab_nav = tab->navigations[i]; 162 TabNavigation& tab_nav = tab->navigations[i];
161 tab_nav.url = entry->display_url(); 163 tab_nav.url = entry->display_url();
162 tab_nav.referrer = entry->referrer(); 164 tab_nav.referrer = entry->referrer();
163 tab_nav.title = entry->title(); 165 tab_nav.title = entry->title();
164 tab_nav.state = entry->content_state(); 166 tab_nav.state = entry->content_state();
165 tab_nav.transition = entry->transition_type(); 167 tab_nav.transition = entry->transition_type();
166 tab_nav.type_mask = entry->has_post_data() ? 168 tab_nav.type_mask = entry->has_post_data() ?
167 TabNavigation::HAS_POST_DATA : 0; 169 TabNavigation::HAS_POST_DATA : 0;
168 } 170 }
169 tab->current_navigation_index = controller->GetCurrentEntryIndex(); 171 tab->current_navigation_index = controller->GetCurrentEntryIndex();
170 if (tab->current_navigation_index == -1 && entry_count > 0) 172 if (tab->current_navigation_index == -1 && entry_count > 0)
171 tab->current_navigation_index = 0; 173 tab->current_navigation_index = 0;
172 } 174 }
173 175
174 void TabRestoreService::PopulateTabFromSessionTab(
175 SessionTab* session_tab,
176 HistoricalTab* tab) {
177 tab->navigations.swap(session_tab->navigations);
178 tab->from_last_session = true;
179 tab->current_navigation_index = session_tab->current_navigation_index;
180 }
181
182 void TabRestoreService::NotifyTabsChanged() { 176 void TabRestoreService::NotifyTabsChanged() {
183 FOR_EACH_OBSERVER(Observer, observer_list_, TabRestoreServiceChanged(this)); 177 FOR_EACH_OBSERVER(Observer, observer_list_, TabRestoreServiceChanged(this));
184 } 178 }
179
180 void TabRestoreService::PruneAndNotify() {
181 while (entries_.size() > kMaxEntries) {
182 delete entries_.back();
183 entries_.pop_back();
184 }
185
186 NotifyTabsChanged();
187 }
188
189 TabRestoreService::Entries::iterator TabRestoreService::GetEntryIteratorById(
190 int id) {
191 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) {
192 if ((*i)->id == id)
193 return i;
194 }
195 return entries_.end();
196 }
OLDNEW
« no previous file with comments | « chrome/browser/tab_restore_service.h ('k') | chrome/browser/tab_restore_uitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698