OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "components/sessions/core/tab_restore_service_helper.h" | 5 #include "components/sessions/core/tab_restore_service_helper.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <iterator> | 10 #include <iterator> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/memory/ptr_util.h" |
13 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
14 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
15 #include "components/sessions/core/live_tab.h" | 16 #include "components/sessions/core/live_tab.h" |
16 #include "components/sessions/core/live_tab_context.h" | 17 #include "components/sessions/core/live_tab_context.h" |
17 #include "components/sessions/core/serialized_navigation_entry.h" | 18 #include "components/sessions/core/serialized_navigation_entry.h" |
18 #include "components/sessions/core/session_types.h" | 19 #include "components/sessions/core/session_types.h" |
19 #include "components/sessions/core/tab_restore_service_client.h" | 20 #include "components/sessions/core/tab_restore_service_client.h" |
20 #include "components/sessions/core/tab_restore_service_observer.h" | 21 #include "components/sessions/core/tab_restore_service_observer.h" |
21 | 22 |
22 namespace sessions { | 23 namespace sessions { |
(...skipping 22 matching lines...) Expand all Loading... |
45 observer_(observer), | 46 observer_(observer), |
46 client_(client), | 47 client_(client), |
47 restoring_(false), | 48 restoring_(false), |
48 time_factory_(time_factory) { | 49 time_factory_(time_factory) { |
49 DCHECK(tab_restore_service_); | 50 DCHECK(tab_restore_service_); |
50 } | 51 } |
51 | 52 |
52 TabRestoreServiceHelper::~TabRestoreServiceHelper() { | 53 TabRestoreServiceHelper::~TabRestoreServiceHelper() { |
53 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, | 54 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
54 TabRestoreServiceDestroyed(tab_restore_service_)); | 55 TabRestoreServiceDestroyed(tab_restore_service_)); |
55 STLDeleteElements(&entries_); | |
56 } | 56 } |
57 | 57 |
58 void TabRestoreServiceHelper::AddObserver( | 58 void TabRestoreServiceHelper::AddObserver( |
59 TabRestoreServiceObserver* observer) { | 59 TabRestoreServiceObserver* observer) { |
60 observer_list_.AddObserver(observer); | 60 observer_list_.AddObserver(observer); |
61 } | 61 } |
62 | 62 |
63 void TabRestoreServiceHelper::RemoveObserver( | 63 void TabRestoreServiceHelper::RemoveObserver( |
64 TabRestoreServiceObserver* observer) { | 64 TabRestoreServiceObserver* observer) { |
65 observer_list_.RemoveObserver(observer); | 65 observer_list_.RemoveObserver(observer); |
66 } | 66 } |
67 | 67 |
68 void TabRestoreServiceHelper::CreateHistoricalTab(LiveTab* live_tab, | 68 void TabRestoreServiceHelper::CreateHistoricalTab(LiveTab* live_tab, |
69 int index) { | 69 int index) { |
70 if (restoring_) | 70 if (restoring_) |
71 return; | 71 return; |
72 | 72 |
73 LiveTabContext* context = client_->FindLiveTabContextForTab(live_tab); | 73 LiveTabContext* context = client_->FindLiveTabContextForTab(live_tab); |
74 if (closing_contexts_.find(context) != closing_contexts_.end()) | 74 if (closing_contexts_.find(context) != closing_contexts_.end()) |
75 return; | 75 return; |
76 | 76 |
77 std::unique_ptr<Tab> local_tab(new Tab()); | 77 auto local_tab = base::MakeUnique<Tab>(); |
78 PopulateTab(local_tab.get(), index, context, live_tab); | 78 PopulateTab(local_tab.get(), index, context, live_tab); |
79 if (local_tab->navigations.empty()) | 79 if (local_tab->navigations.empty()) |
80 return; | 80 return; |
81 | 81 |
82 AddEntry(local_tab.release(), true, true); | 82 AddEntry(std::move(local_tab), true, true); |
83 } | 83 } |
84 | 84 |
85 void TabRestoreServiceHelper::BrowserClosing(LiveTabContext* context) { | 85 void TabRestoreServiceHelper::BrowserClosing(LiveTabContext* context) { |
86 closing_contexts_.insert(context); | 86 closing_contexts_.insert(context); |
87 | 87 |
88 std::unique_ptr<Window> window(new Window()); | 88 auto window = base::MakeUnique<Window>(); |
89 window->selected_tab_index = context->GetSelectedIndex(); | 89 window->selected_tab_index = context->GetSelectedIndex(); |
90 window->timestamp = TimeNow(); | 90 window->timestamp = TimeNow(); |
91 window->app_name = context->GetAppName(); | 91 window->app_name = context->GetAppName(); |
92 | 92 |
93 // Don't use std::vector::resize() because it will push copies of an empty tab | |
94 // into the vector, which will give all tabs in a window the same ID. | |
95 for (int i = 0; i < context->GetTabCount(); ++i) { | |
96 window->tabs.push_back(Tab()); | |
97 } | |
98 size_t entry_index = 0; | |
99 for (int tab_index = 0; tab_index < context->GetTabCount(); ++tab_index) { | 93 for (int tab_index = 0; tab_index < context->GetTabCount(); ++tab_index) { |
100 PopulateTab(&(window->tabs[entry_index]), tab_index, context, | 94 auto tab = base::MakeUnique<Tab>(); |
| 95 PopulateTab(tab.get(), tab_index, context, |
101 context->GetLiveTabAt(tab_index)); | 96 context->GetLiveTabAt(tab_index)); |
102 if (window->tabs[entry_index].navigations.empty()) { | 97 if (!tab->navigations.empty()) { |
103 window->tabs.erase(window->tabs.begin() + entry_index); | 98 tab->browser_id = context->GetSessionID().id(); |
104 } else { | 99 window->tabs.push_back(std::move(tab)); |
105 window->tabs[entry_index].browser_id = context->GetSessionID().id(); | |
106 entry_index++; | |
107 } | 100 } |
108 } | 101 } |
109 if (window->tabs.size() == 1 && window->app_name.empty()) { | 102 if (window->tabs.size() == 1 && window->app_name.empty()) { |
110 // Short-circuit creating a Window if only 1 tab was present. This fixes | 103 // Short-circuit creating a Window if only 1 tab was present. This fixes |
111 // http://crbug.com/56744. Copy the Tab because it's owned by an object on | 104 // http://crbug.com/56744. |
112 // the stack. | 105 AddEntry(std::move(window->tabs[0]), true, true); |
113 AddEntry(new Tab(window->tabs[0]), true, true); | |
114 } else if (!window->tabs.empty()) { | 106 } else if (!window->tabs.empty()) { |
115 window->selected_tab_index = | 107 window->selected_tab_index = std::min( |
116 std::min(static_cast<int>(window->tabs.size() - 1), | 108 static_cast<int>(window->tabs.size() - 1), window->selected_tab_index); |
117 window->selected_tab_index); | 109 AddEntry(std::move(window), true, true); |
118 AddEntry(window.release(), true, true); | |
119 } | 110 } |
120 } | 111 } |
121 | 112 |
122 void TabRestoreServiceHelper::BrowserClosed(LiveTabContext* context) { | 113 void TabRestoreServiceHelper::BrowserClosed(LiveTabContext* context) { |
123 closing_contexts_.erase(context); | 114 closing_contexts_.erase(context); |
124 } | 115 } |
125 | 116 |
126 void TabRestoreServiceHelper::ClearEntries() { | 117 void TabRestoreServiceHelper::ClearEntries() { |
127 if (observer_) | 118 if (observer_) |
128 observer_->OnClearEntries(); | 119 observer_->OnClearEntries(); |
129 STLDeleteElements(&entries_); | 120 entries_.clear(); |
130 NotifyTabsChanged(); | 121 NotifyTabsChanged(); |
131 } | 122 } |
132 | 123 |
133 const TabRestoreService::Entries& TabRestoreServiceHelper::entries() const { | 124 const TabRestoreService::Entries& TabRestoreServiceHelper::entries() const { |
134 return entries_; | 125 return entries_; |
135 } | 126 } |
136 | 127 |
137 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreMostRecentEntry( | 128 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreMostRecentEntry( |
138 LiveTabContext* context) { | 129 LiveTabContext* context) { |
139 if (entries_.empty()) | 130 if (entries_.empty()) |
140 return std::vector<LiveTab*>(); | 131 return std::vector<LiveTab*>(); |
141 return RestoreEntryById(context, entries_.front()->id, UNKNOWN); | 132 return RestoreEntryById(context, entries_.front()->id, UNKNOWN); |
142 } | 133 } |
143 | 134 |
144 TabRestoreService::Tab* TabRestoreServiceHelper::RemoveTabEntryById( | 135 std::unique_ptr<TabRestoreService::Tab> |
145 SessionID::id_type id) { | 136 TabRestoreServiceHelper::RemoveTabEntryById(SessionID::id_type id) { |
146 Entries::iterator it = GetEntryIteratorById(id); | 137 auto it = GetEntryIteratorById(id); |
147 if (it == entries_.end()) | 138 if (it == entries_.end()) |
148 return nullptr; | 139 return nullptr; |
149 | 140 |
150 Entry* entry = *it; | 141 if ((*it)->type != TabRestoreService::TAB) |
151 if (entry->type != TabRestoreService::TAB) | |
152 return nullptr; | 142 return nullptr; |
153 | 143 |
154 Tab* tab = static_cast<Tab*>(entry); | 144 auto tab = std::unique_ptr<Tab>(static_cast<Tab*>(it->release())); |
155 entries_.erase(it); | 145 entries_.erase(it); |
156 return tab; | 146 return tab; |
157 } | 147 } |
158 | 148 |
159 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById( | 149 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById( |
160 LiveTabContext* context, | 150 LiveTabContext* context, |
161 SessionID::id_type id, | 151 SessionID::id_type id, |
162 WindowOpenDisposition disposition) { | 152 WindowOpenDisposition disposition) { |
163 Entries::iterator entry_iterator = GetEntryIteratorById(id); | 153 Entries::iterator entry_iterator = GetEntryIteratorById(id); |
164 if (entry_iterator == entries_.end()) { | 154 if (entry_iterator == entries_.end()) { |
165 // Don't hoark here, we allow an invalid id. | 155 // Don't hoark here, we allow an invalid id. |
166 return std::vector<LiveTab*>(); | 156 return std::vector<LiveTab*>(); |
167 } | 157 } |
168 | 158 |
169 if (observer_) | 159 if (observer_) |
170 observer_->OnRestoreEntryById(id, entry_iterator); | 160 observer_->OnRestoreEntryById(id, entry_iterator); |
171 restoring_ = true; | 161 restoring_ = true; |
172 Entry* entry = *entry_iterator; | 162 auto& entry = **entry_iterator; |
173 | 163 |
174 // If the entry's ID does not match the ID that is being restored, then the | 164 // If the entry's ID does not match the ID that is being restored, then the |
175 // entry is a window from which a single tab will be restored. | 165 // entry is a window from which a single tab will be restored. |
176 bool restoring_tab_in_window = entry->id != id; | 166 bool restoring_tab_in_window = entry.id != id; |
177 | |
178 if (!restoring_tab_in_window) { | |
179 entries_.erase(entry_iterator); | |
180 entry_iterator = entries_.end(); | |
181 } | |
182 | 167 |
183 // |context| will be NULL in cases where one isn't already available (eg, | 168 // |context| will be NULL in cases where one isn't already available (eg, |
184 // when invoked on Mac OS X with no windows open). In this case, create a | 169 // when invoked on Mac OS X with no windows open). In this case, create a |
185 // new browser into which we restore the tabs. | 170 // new browser into which we restore the tabs. |
186 std::vector<LiveTab*> live_tabs; | 171 std::vector<LiveTab*> live_tabs; |
187 if (entry->type == TabRestoreService::TAB) { | 172 switch (entry.type) { |
188 Tab* tab = static_cast<Tab*>(entry); | 173 case TabRestoreService::TAB: { |
189 LiveTab* restored_tab = nullptr; | 174 auto& tab = static_cast<const Tab&>(entry); |
190 context = RestoreTab(*tab, context, disposition, &restored_tab); | 175 LiveTab* restored_tab = nullptr; |
191 live_tabs.push_back(restored_tab); | 176 context = RestoreTab(tab, context, disposition, &restored_tab); |
192 context->ShowBrowserWindow(); | 177 live_tabs.push_back(restored_tab); |
193 } else if (entry->type == TabRestoreService::WINDOW) { | 178 context->ShowBrowserWindow(); |
194 LiveTabContext* current_context = context; | 179 break; |
195 Window* window = static_cast<Window*>(entry); | 180 } |
| 181 case TabRestoreService::WINDOW: { |
| 182 LiveTabContext* current_context = context; |
| 183 auto& window = static_cast<Window&>(entry); |
196 | 184 |
197 // When restoring a window, either the entire window can be restored, or a | 185 // When restoring a window, either the entire window can be restored, or a |
198 // single tab within it. If the entry's ID matches the one to restore, then | 186 // single tab within it. If the entry's ID matches the one to restore, |
199 // the entire window will be restored. | 187 // then the entire window will be restored. |
200 if (!restoring_tab_in_window) { | 188 if (!restoring_tab_in_window) { |
201 context = client_->CreateLiveTabContext(window->app_name); | 189 context = client_->CreateLiveTabContext(window.app_name); |
202 for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) { | 190 for (size_t tab_i = 0; tab_i < window.tabs.size(); ++tab_i) { |
203 const Tab& tab = window->tabs[tab_i]; | 191 const Tab& tab = *window.tabs[tab_i]; |
204 LiveTab* restored_tab = context->AddRestoredTab( | 192 LiveTab* restored_tab = context->AddRestoredTab( |
205 tab.navigations, context->GetTabCount(), | 193 tab.navigations, context->GetTabCount(), |
206 tab.current_navigation_index, tab.extension_app_id, | 194 tab.current_navigation_index, tab.extension_app_id, |
207 static_cast<int>(tab_i) == window->selected_tab_index, tab.pinned, | 195 static_cast<int>(tab_i) == window.selected_tab_index, tab.pinned, |
208 tab.from_last_session, tab.platform_data.get(), | 196 tab.from_last_session, tab.platform_data.get(), |
209 tab.user_agent_override); | 197 tab.user_agent_override); |
210 if (restored_tab) { | 198 if (restored_tab) { |
211 restored_tab->LoadIfNecessary(); | 199 restored_tab->LoadIfNecessary(); |
212 client_->OnTabRestored( | 200 client_->OnTabRestored( |
213 tab.navigations.at(tab.current_navigation_index).virtual_url()); | 201 tab.navigations.at(tab.current_navigation_index).virtual_url()); |
214 live_tabs.push_back(restored_tab); | 202 live_tabs.push_back(restored_tab); |
| 203 } |
| 204 } |
| 205 // All the window's tabs had the same former browser_id. |
| 206 if (auto browser_id = window.tabs[0]->browser_id) { |
| 207 UpdateTabBrowserIDs(browser_id, context->GetSessionID().id()); |
| 208 } |
| 209 } else { |
| 210 // Restore a single tab from the window. Find the tab that matches the |
| 211 // ID |
| 212 // in the window and restore it. |
| 213 for (auto tab_i = window.tabs.begin(); tab_i != window.tabs.end(); |
| 214 ++tab_i) { |
| 215 SessionID::id_type restored_tab_browser_id; |
| 216 { |
| 217 const Tab& tab = **tab_i; |
| 218 if (tab.id != id) |
| 219 continue; |
| 220 |
| 221 restored_tab_browser_id = tab.browser_id; |
| 222 LiveTab* restored_tab = nullptr; |
| 223 context = RestoreTab(tab, context, disposition, &restored_tab); |
| 224 live_tabs.push_back(restored_tab); |
| 225 window.tabs.erase(tab_i); |
| 226 } |
| 227 // If restoring the tab leaves the window with nothing else, delete it |
| 228 // as well. |
| 229 if (window.tabs.empty()) { |
| 230 entries_.erase(entry_iterator); |
| 231 } else { |
| 232 // Update the browser ID of the rest of the tabs in the window so if |
| 233 // any one is restored, it goes into the same window as the tab |
| 234 // being restored now. |
| 235 UpdateTabBrowserIDs(restored_tab_browser_id, |
| 236 context->GetSessionID().id()); |
| 237 for (auto& tab_j : window.tabs) |
| 238 tab_j->browser_id = context->GetSessionID().id(); |
| 239 } |
| 240 break; |
215 } | 241 } |
216 } | 242 } |
217 // All the window's tabs had the same former browser_id. | 243 context->ShowBrowserWindow(); |
218 if (window->tabs[0].has_browser()) { | 244 |
219 UpdateTabBrowserIDs(window->tabs[0].browser_id, | 245 if (disposition == CURRENT_TAB && current_context && |
220 context->GetSessionID().id()); | 246 current_context->GetActiveLiveTab()) { |
| 247 current_context->CloseTab(); |
221 } | 248 } |
222 } else { | 249 break; |
223 // Restore a single tab from the window. Find the tab that matches the ID | |
224 // in the window and restore it. | |
225 for (std::vector<Tab>::iterator tab_i = window->tabs.begin(); | |
226 tab_i != window->tabs.end(); ++tab_i) { | |
227 const Tab& tab = *tab_i; | |
228 if (tab.id != id) | |
229 continue; | |
230 | |
231 LiveTab* restored_tab = nullptr; | |
232 context = RestoreTab(tab, context, disposition, &restored_tab); | |
233 live_tabs.push_back(restored_tab); | |
234 window->tabs.erase(tab_i); | |
235 // If restoring the tab leaves the window with nothing else, delete it | |
236 // as well. | |
237 if (window->tabs.empty()) { | |
238 entries_.erase(entry_iterator); | |
239 delete entry; | |
240 } else { | |
241 // Update the browser ID of the rest of the tabs in the window so if | |
242 // any one is restored, it goes into the same window as the tab | |
243 // being restored now. | |
244 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); | |
245 for (Tab& tab_j : window->tabs) | |
246 tab_j.browser_id = context->GetSessionID().id(); | |
247 } | |
248 break; | |
249 } | |
250 } | 250 } |
251 context->ShowBrowserWindow(); | |
252 | |
253 if (disposition == CURRENT_TAB && current_context && | |
254 current_context->GetActiveLiveTab()) { | |
255 current_context->CloseTab(); | |
256 } | |
257 } else { | |
258 NOTREACHED(); | |
259 } | 251 } |
260 | 252 |
261 if (!restoring_tab_in_window) { | 253 if (!restoring_tab_in_window) { |
262 delete entry; | 254 entries_.erase(entry_iterator); |
263 } | 255 } |
264 | 256 |
265 restoring_ = false; | 257 restoring_ = false; |
266 NotifyTabsChanged(); | 258 NotifyTabsChanged(); |
267 return live_tabs; | 259 return live_tabs; |
268 } | 260 } |
269 | 261 |
270 void TabRestoreServiceHelper::NotifyTabsChanged() { | 262 void TabRestoreServiceHelper::NotifyTabsChanged() { |
271 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, | 263 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
272 TabRestoreServiceChanged(tab_restore_service_)); | 264 TabRestoreServiceChanged(tab_restore_service_)); |
273 } | 265 } |
274 | 266 |
275 void TabRestoreServiceHelper::NotifyLoaded() { | 267 void TabRestoreServiceHelper::NotifyLoaded() { |
276 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, | 268 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
277 TabRestoreServiceLoaded(tab_restore_service_)); | 269 TabRestoreServiceLoaded(tab_restore_service_)); |
278 } | 270 } |
279 | 271 |
280 void TabRestoreServiceHelper::AddEntry(Entry* entry, | 272 void TabRestoreServiceHelper::AddEntry(std::unique_ptr<Entry> entry, |
281 bool notify, | 273 bool notify, |
282 bool to_front) { | 274 bool to_front) { |
283 if (!FilterEntry(entry) || (entries_.size() >= kMaxEntries && !to_front)) { | 275 if (!FilterEntry(*entry) || (entries_.size() >= kMaxEntries && !to_front)) { |
284 delete entry; | |
285 return; | 276 return; |
286 } | 277 } |
287 | 278 |
288 if (to_front) | 279 if (to_front) |
289 entries_.push_front(entry); | 280 entries_.push_front(std::move(entry)); |
290 else | 281 else |
291 entries_.push_back(entry); | 282 entries_.push_back(std::move(entry)); |
292 | 283 |
293 PruneEntries(); | 284 PruneEntries(); |
294 | 285 |
295 if (notify) | 286 if (notify) |
296 NotifyTabsChanged(); | 287 NotifyTabsChanged(); |
297 | 288 |
298 if (observer_) | 289 if (observer_) |
299 observer_->OnAddEntry(); | 290 observer_->OnAddEntry(); |
300 } | 291 } |
301 | 292 |
302 void TabRestoreServiceHelper::PruneEntries() { | 293 void TabRestoreServiceHelper::PruneEntries() { |
303 Entries new_entries; | 294 Entries new_entries; |
304 | 295 |
305 for (TabRestoreService::Entries::const_iterator iter = entries_.begin(); | 296 for (auto& entry : entries_) { |
306 iter != entries_.end(); ++iter) { | 297 if (FilterEntry(*entry) && new_entries.size() < kMaxEntries) { |
307 TabRestoreService::Entry* entry = *iter; | 298 new_entries.push_back(std::move(entry)); |
308 | |
309 if (FilterEntry(entry) && | |
310 new_entries.size() < kMaxEntries) { | |
311 new_entries.push_back(entry); | |
312 } else { | |
313 delete entry; | |
314 } | 299 } |
315 } | 300 } |
316 | 301 |
317 entries_ = new_entries; | 302 entries_ = std::move(new_entries); |
318 } | 303 } |
319 | 304 |
320 TabRestoreService::Entries::iterator | 305 TabRestoreService::Entries::iterator |
321 TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) { | 306 TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) { |
322 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { | 307 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { |
323 if ((*i)->id == id) | 308 if ((*i)->id == id) |
324 return i; | 309 return i; |
325 | 310 |
326 // For Window entries, see if the ID matches a tab. If so, report the window | 311 // For Window entries, see if the ID matches a tab. If so, report the window |
327 // as the Entry. | 312 // as the Entry. |
328 if ((*i)->type == TabRestoreService::WINDOW) { | 313 if ((*i)->type == TabRestoreService::WINDOW) { |
329 std::vector<Tab>& tabs = static_cast<Window*>(*i)->tabs; | 314 auto& window = static_cast<const Window&>(**i); |
330 for (std::vector<Tab>::iterator j = tabs.begin(); | 315 for (const auto& tab : window.tabs) { |
331 j != tabs.end(); ++j) { | 316 if (tab->id == id) { |
332 if ((*j).id == id) { | |
333 return i; | 317 return i; |
334 } | 318 } |
335 } | 319 } |
336 } | 320 } |
337 } | 321 } |
338 return entries_.end(); | 322 return entries_.end(); |
339 } | 323 } |
340 | 324 |
341 // static | 325 // static |
342 bool TabRestoreServiceHelper::ValidateEntry(Entry* entry) { | 326 bool TabRestoreServiceHelper::ValidateEntry(const Entry& entry) { |
343 if (entry->type == TabRestoreService::TAB) | 327 switch (entry.type) { |
344 return ValidateTab(static_cast<Tab*>(entry)); | 328 case TabRestoreService::TAB: |
345 | 329 return ValidateTab(static_cast<const Tab&>(entry)); |
346 if (entry->type == TabRestoreService::WINDOW) | 330 case TabRestoreService::WINDOW: |
347 return ValidateWindow(static_cast<Window*>(entry)); | 331 return ValidateWindow(static_cast<const Window&>(entry)); |
348 | 332 } |
349 NOTREACHED(); | 333 NOTREACHED(); |
350 return false; | 334 return false; |
351 } | 335 } |
352 | 336 |
353 void TabRestoreServiceHelper::PopulateTab(Tab* tab, | 337 void TabRestoreServiceHelper::PopulateTab(Tab* tab, |
354 int index, | 338 int index, |
355 LiveTabContext* context, | 339 LiveTabContext* context, |
356 LiveTab* live_tab) { | 340 LiveTab* live_tab) { |
357 const int pending_index = live_tab->GetPendingEntryIndex(); | 341 const int pending_index = live_tab->GetPendingEntryIndex(); |
358 int entry_count = | 342 int entry_count = |
359 live_tab->IsInitialBlankNavigation() ? 0 : live_tab->GetEntryCount(); | 343 live_tab->IsInitialBlankNavigation() ? 0 : live_tab->GetEntryCount(); |
360 if (entry_count == 0 && pending_index == 0) | 344 if (entry_count == 0 && pending_index == 0) |
361 entry_count++; | 345 entry_count++; |
362 tab->navigations.resize(static_cast<int>(entry_count)); | 346 tab->navigations.resize(static_cast<int>(entry_count)); |
363 for (int i = 0; i < entry_count; ++i) { | 347 for (int i = 0; i < entry_count; ++i) { |
364 SerializedNavigationEntry entry = (i == pending_index) | 348 SerializedNavigationEntry entry = (i == pending_index) |
365 ? live_tab->GetPendingEntry() | 349 ? live_tab->GetPendingEntry() |
366 : live_tab->GetEntryAtIndex(i); | 350 : live_tab->GetEntryAtIndex(i); |
367 tab->navigations[i] = entry; | 351 tab->navigations[i] = entry; |
368 } | 352 } |
369 tab->timestamp = TimeNow(); | 353 tab->timestamp = TimeNow(); |
370 tab->current_navigation_index = live_tab->GetCurrentEntryIndex(); | 354 tab->current_navigation_index = live_tab->GetCurrentEntryIndex(); |
371 if (tab->current_navigation_index == -1 && entry_count > 0) | |
372 tab->current_navigation_index = 0; | |
373 tab->tabstrip_index = index; | 355 tab->tabstrip_index = index; |
374 | 356 |
375 tab->extension_app_id = client_->GetExtensionAppIDForTab(live_tab); | 357 tab->extension_app_id = client_->GetExtensionAppIDForTab(live_tab); |
376 | 358 |
377 tab->user_agent_override = live_tab->GetUserAgentOverride(); | 359 tab->user_agent_override = live_tab->GetUserAgentOverride(); |
378 | 360 |
379 tab->platform_data = live_tab->GetPlatformSpecificTabData(); | 361 tab->platform_data = live_tab->GetPlatformSpecificTabData(); |
380 | 362 |
381 // Delegate may be NULL during unit tests. | 363 // Delegate may be NULL during unit tests. |
382 if (context) { | 364 if (context) { |
383 tab->browser_id = context->GetSessionID().id(); | 365 tab->browser_id = context->GetSessionID().id(); |
384 tab->pinned = context->IsTabPinned(tab->tabstrip_index); | 366 tab->pinned = context->IsTabPinned(tab->tabstrip_index); |
385 } | 367 } |
386 } | 368 } |
387 | 369 |
388 LiveTabContext* TabRestoreServiceHelper::RestoreTab( | 370 LiveTabContext* TabRestoreServiceHelper::RestoreTab( |
389 const Tab& tab, | 371 const Tab& tab, |
390 LiveTabContext* context, | 372 LiveTabContext* context, |
391 WindowOpenDisposition disposition, | 373 WindowOpenDisposition disposition, |
392 LiveTab** live_tab) { | 374 LiveTab** live_tab) { |
393 LiveTab* restored_tab; | 375 LiveTab* restored_tab; |
394 if (disposition == CURRENT_TAB && context) { | 376 if (disposition == CURRENT_TAB && context) { |
395 restored_tab = context->ReplaceRestoredTab( | 377 restored_tab = context->ReplaceRestoredTab( |
396 tab.navigations, tab.current_navigation_index, tab.from_last_session, | 378 tab.navigations, tab.current_navigation_index, tab.from_last_session, |
397 tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override); | 379 tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override); |
398 } else { | 380 } else { |
399 // We only respsect the tab's original browser if there's no disposition. | 381 // We only respsect the tab's original browser if there's no disposition. |
400 if (disposition == UNKNOWN && tab.has_browser()) { | 382 if (disposition == UNKNOWN && tab.browser_id) { |
401 context = client_->FindLiveTabContextWithID(tab.browser_id); | 383 context = client_->FindLiveTabContextWithID(tab.browser_id); |
402 } | 384 } |
403 | 385 |
404 int tab_index = -1; | 386 int tab_index = -1; |
405 | 387 |
406 // |context| will be NULL in cases where one isn't already available (eg, | 388 // |context| will be NULL in cases where one isn't already available (eg, |
407 // when invoked on Mac OS X with no windows open). In this case, create a | 389 // when invoked on Mac OS X with no windows open). In this case, create a |
408 // new browser into which we restore the tabs. | 390 // new browser into which we restore the tabs. |
409 if (context && disposition != NEW_WINDOW) { | 391 if (context && disposition != NEW_WINDOW) { |
410 tab_index = tab.tabstrip_index; | 392 tab_index = tab.tabstrip_index; |
411 } else { | 393 } else { |
412 context = client_->CreateLiveTabContext(std::string()); | 394 context = client_->CreateLiveTabContext(std::string()); |
413 if (tab.has_browser()) | 395 if (tab.browser_id) |
414 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); | 396 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); |
415 } | 397 } |
416 | 398 |
417 // Place the tab at the end if the tab index is no longer valid or | 399 // Place the tab at the end if the tab index is no longer valid or |
418 // we were passed a specific disposition. | 400 // we were passed a specific disposition. |
419 if (tab_index < 0 || tab_index > context->GetTabCount() || | 401 if (tab_index < 0 || tab_index > context->GetTabCount() || |
420 disposition != UNKNOWN) { | 402 disposition != UNKNOWN) { |
421 tab_index = context->GetTabCount(); | 403 tab_index = context->GetTabCount(); |
422 } | 404 } |
423 | 405 |
424 restored_tab = context->AddRestoredTab( | 406 restored_tab = context->AddRestoredTab( |
425 tab.navigations, tab_index, tab.current_navigation_index, | 407 tab.navigations, tab_index, tab.current_navigation_index, |
426 tab.extension_app_id, disposition != NEW_BACKGROUND_TAB, tab.pinned, | 408 tab.extension_app_id, disposition != NEW_BACKGROUND_TAB, tab.pinned, |
427 tab.from_last_session, tab.platform_data.get(), | 409 tab.from_last_session, tab.platform_data.get(), |
428 tab.user_agent_override); | 410 tab.user_agent_override); |
429 restored_tab->LoadIfNecessary(); | 411 restored_tab->LoadIfNecessary(); |
430 } | 412 } |
431 client_->OnTabRestored( | 413 client_->OnTabRestored( |
432 tab.navigations.at(tab.current_navigation_index).virtual_url()); | 414 tab.navigations.at(tab.current_navigation_index).virtual_url()); |
433 if (live_tab) | 415 if (live_tab) |
434 *live_tab = restored_tab; | 416 *live_tab = restored_tab; |
435 | 417 |
436 return context; | 418 return context; |
437 } | 419 } |
438 | 420 |
| 421 bool TabRestoreServiceHelper::ValidateTab(const Tab& tab) { |
| 422 return !tab.navigations.empty() && |
| 423 static_cast<size_t>(tab.current_navigation_index) < |
| 424 tab.navigations.size(); |
| 425 } |
439 | 426 |
440 bool TabRestoreServiceHelper::ValidateTab(Tab* tab) { | 427 bool TabRestoreServiceHelper::ValidateWindow(const Window& window) { |
441 if (tab->navigations.empty()) | 428 if (static_cast<size_t>(window.selected_tab_index) >= window.tabs.size()) { |
442 return false; | 429 return false; |
| 430 } |
443 | 431 |
444 tab->current_navigation_index = | 432 for (const auto& tab : window.tabs) { |
445 std::max(0, std::min(tab->current_navigation_index, | 433 if (!ValidateTab(*tab)) { |
446 static_cast<int>(tab->navigations.size()) - 1)); | 434 return false; |
| 435 } |
| 436 } |
447 | 437 |
448 return true; | 438 return true; |
449 } | 439 } |
450 | 440 |
451 bool TabRestoreServiceHelper::ValidateWindow(Window* window) { | 441 bool TabRestoreServiceHelper::IsTabInteresting(const Tab& tab) { |
452 window->selected_tab_index = | 442 if (tab.navigations.empty()) |
453 std::max(0, std::min(window->selected_tab_index, | |
454 static_cast<int>(window->tabs.size() - 1))); | |
455 | |
456 int i = 0; | |
457 for (std::vector<Tab>::iterator tab_i = window->tabs.begin(); | |
458 tab_i != window->tabs.end();) { | |
459 if (!ValidateTab(&(*tab_i))) { | |
460 tab_i = window->tabs.erase(tab_i); | |
461 if (i < window->selected_tab_index) | |
462 window->selected_tab_index--; | |
463 else if (i == window->selected_tab_index) | |
464 window->selected_tab_index = 0; | |
465 } else { | |
466 ++tab_i; | |
467 ++i; | |
468 } | |
469 } | |
470 | |
471 if (window->tabs.empty()) | |
472 return false; | 443 return false; |
473 | 444 |
474 return true; | 445 if (tab.navigations.size() > 1) |
| 446 return true; |
| 447 |
| 448 return tab.pinned || |
| 449 tab.navigations.at(0).virtual_url() != client_->GetNewTabURL(); |
475 } | 450 } |
476 | 451 |
477 bool TabRestoreServiceHelper::IsTabInteresting(const Tab* tab) { | 452 bool TabRestoreServiceHelper::IsWindowInteresting(const Window& window) { |
478 if (tab->navigations.empty()) | 453 if (window.tabs.empty()) |
479 return false; | 454 return false; |
480 | 455 |
481 if (tab->navigations.size() > 1) | 456 if (window.tabs.size() > 1) |
482 return true; | 457 return true; |
483 | 458 |
484 return tab->pinned || | 459 return IsTabInteresting(*window.tabs[0]); |
485 tab->navigations.at(0).virtual_url() != client_->GetNewTabURL(); | |
486 } | 460 } |
487 | 461 |
488 bool TabRestoreServiceHelper::IsWindowInteresting(const Window* window) { | 462 bool TabRestoreServiceHelper::FilterEntry(const Entry& entry) { |
489 if (window->tabs.empty()) | |
490 return false; | |
491 | |
492 if (window->tabs.size() > 1) | |
493 return true; | |
494 | |
495 return IsTabInteresting(&window->tabs[0]); | |
496 } | |
497 | |
498 bool TabRestoreServiceHelper::FilterEntry(Entry* entry) { | |
499 if (!ValidateEntry(entry)) | 463 if (!ValidateEntry(entry)) |
500 return false; | 464 return false; |
501 | 465 |
502 if (entry->type == TabRestoreService::TAB) | 466 switch (entry.type) { |
503 return IsTabInteresting(static_cast<Tab*>(entry)); | 467 case TabRestoreService::TAB: |
504 else if (entry->type == TabRestoreService::WINDOW) | 468 return IsTabInteresting(static_cast<const Tab&>(entry)); |
505 return IsWindowInteresting(static_cast<Window*>(entry)); | 469 case TabRestoreService::WINDOW: |
506 | 470 return IsWindowInteresting(static_cast<const Window&>(entry)); |
| 471 } |
507 NOTREACHED(); | 472 NOTREACHED(); |
508 return false; | 473 return false; |
509 } | 474 } |
510 | 475 |
511 void TabRestoreServiceHelper::UpdateTabBrowserIDs(SessionID::id_type old_id, | 476 void TabRestoreServiceHelper::UpdateTabBrowserIDs(SessionID::id_type old_id, |
512 SessionID::id_type new_id) { | 477 SessionID::id_type new_id) { |
513 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { | 478 for (const auto& entry : entries_) { |
514 Entry* entry = *i; | |
515 if (entry->type == TabRestoreService::TAB) { | 479 if (entry->type == TabRestoreService::TAB) { |
516 Tab* tab = static_cast<Tab*>(entry); | 480 auto& tab = static_cast<Tab&>(*entry); |
517 if (tab->browser_id == old_id) | 481 if (tab.browser_id == old_id) |
518 tab->browser_id = new_id; | 482 tab.browser_id = new_id; |
519 } | 483 } |
520 } | 484 } |
521 } | 485 } |
522 | 486 |
523 base::Time TabRestoreServiceHelper::TimeNow() const { | 487 base::Time TabRestoreServiceHelper::TimeNow() const { |
524 return time_factory_ ? time_factory_->TimeNow() : base::Time::Now(); | 488 return time_factory_ ? time_factory_->TimeNow() : base::Time::Now(); |
525 } | 489 } |
526 | 490 |
527 } // namespace sessions | 491 } // namespace sessions |
OLD | NEW |