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 size_t 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 = |
116 std::min(static_cast<int>(window->tabs.size() - 1), | 108 std::min(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 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()); |
| 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 const Tab& tab = **tab_i; |
| 216 if (tab.id != id) |
| 217 continue; |
| 218 |
| 219 LiveTab* restored_tab = nullptr; |
| 220 context = RestoreTab(tab, context, disposition, &restored_tab); |
214 live_tabs.push_back(restored_tab); | 221 live_tabs.push_back(restored_tab); |
| 222 window.tabs.erase(tab_i); |
| 223 // If restoring the tab leaves the window with nothing else, delete it |
| 224 // as well. |
| 225 if (window.tabs.empty()) { |
| 226 entries_.erase(entry_iterator); |
| 227 } else { |
| 228 // Update the browser ID of the rest of the tabs in the window so if |
| 229 // any one is restored, it goes into the same window as the tab |
| 230 // being restored now. |
| 231 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); |
| 232 for (auto& tab_j : window.tabs) |
| 233 tab_j->browser_id = context->GetSessionID().id(); |
| 234 } |
| 235 break; |
215 } | 236 } |
216 } | 237 } |
217 // All the window's tabs had the same former browser_id. | 238 context->ShowBrowserWindow(); |
218 if (window->tabs[0].has_browser()) { | 239 |
219 UpdateTabBrowserIDs(window->tabs[0].browser_id, | 240 if (disposition == CURRENT_TAB && current_context && |
220 context->GetSessionID().id()); | 241 current_context->GetActiveLiveTab()) { |
| 242 current_context->CloseTab(); |
221 } | 243 } |
222 } else { | 244 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 } | 245 } |
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 } | 246 } |
260 | 247 |
261 if (!restoring_tab_in_window) { | 248 if (!restoring_tab_in_window) { |
262 delete entry; | 249 entries_.erase(entry_iterator); |
263 } | 250 } |
264 | 251 |
265 restoring_ = false; | 252 restoring_ = false; |
266 NotifyTabsChanged(); | 253 NotifyTabsChanged(); |
267 return live_tabs; | 254 return live_tabs; |
268 } | 255 } |
269 | 256 |
270 void TabRestoreServiceHelper::NotifyTabsChanged() { | 257 void TabRestoreServiceHelper::NotifyTabsChanged() { |
271 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, | 258 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
272 TabRestoreServiceChanged(tab_restore_service_)); | 259 TabRestoreServiceChanged(tab_restore_service_)); |
273 } | 260 } |
274 | 261 |
275 void TabRestoreServiceHelper::NotifyLoaded() { | 262 void TabRestoreServiceHelper::NotifyLoaded() { |
276 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, | 263 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
277 TabRestoreServiceLoaded(tab_restore_service_)); | 264 TabRestoreServiceLoaded(tab_restore_service_)); |
278 } | 265 } |
279 | 266 |
280 void TabRestoreServiceHelper::AddEntry(Entry* entry, | 267 void TabRestoreServiceHelper::AddEntry(std::unique_ptr<Entry> entry, |
281 bool notify, | 268 bool notify, |
282 bool to_front) { | 269 bool to_front) { |
283 if (!FilterEntry(entry) || (entries_.size() >= kMaxEntries && !to_front)) { | 270 if (!FilterEntry(*entry) || (entries_.size() >= kMaxEntries && !to_front)) { |
284 delete entry; | |
285 return; | 271 return; |
286 } | 272 } |
287 | 273 |
288 if (to_front) | 274 if (to_front) |
289 entries_.push_front(entry); | 275 entries_.push_front(std::move(entry)); |
290 else | 276 else |
291 entries_.push_back(entry); | 277 entries_.push_back(std::move(entry)); |
292 | 278 |
293 PruneEntries(); | 279 PruneEntries(); |
294 | 280 |
295 if (notify) | 281 if (notify) |
296 NotifyTabsChanged(); | 282 NotifyTabsChanged(); |
297 | 283 |
298 if (observer_) | 284 if (observer_) |
299 observer_->OnAddEntry(); | 285 observer_->OnAddEntry(); |
300 } | 286 } |
301 | 287 |
302 void TabRestoreServiceHelper::PruneEntries() { | 288 void TabRestoreServiceHelper::PruneEntries() { |
303 Entries new_entries; | 289 Entries new_entries; |
304 | 290 |
305 for (TabRestoreService::Entries::const_iterator iter = entries_.begin(); | 291 for (auto &entry : entries_) { |
306 iter != entries_.end(); ++iter) { | 292 if (FilterEntry(*entry) && new_entries.size() < kMaxEntries) { |
307 TabRestoreService::Entry* entry = *iter; | 293 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 } | 294 } |
315 } | 295 } |
316 | 296 |
317 entries_ = new_entries; | 297 entries_ = std::move(new_entries); |
318 } | 298 } |
319 | 299 |
320 TabRestoreService::Entries::iterator | 300 TabRestoreService::Entries::iterator |
321 TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) { | 301 TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) { |
322 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { | 302 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { |
323 if ((*i)->id == id) | 303 if ((*i)->id == id) |
324 return i; | 304 return i; |
325 | 305 |
326 // For Window entries, see if the ID matches a tab. If so, report the window | 306 // For Window entries, see if the ID matches a tab. If so, report the window |
327 // as the Entry. | 307 // as the Entry. |
328 if ((*i)->type == TabRestoreService::WINDOW) { | 308 if ((*i)->type() == TabRestoreService::WINDOW) { |
329 std::vector<Tab>& tabs = static_cast<Window*>(*i)->tabs; | 309 auto &window = static_cast<const Window&>(**i); |
330 for (std::vector<Tab>::iterator j = tabs.begin(); | 310 for (const auto &tab : window.tabs) { |
331 j != tabs.end(); ++j) { | 311 if (tab->id == id) { |
332 if ((*j).id == id) { | |
333 return i; | 312 return i; |
334 } | 313 } |
335 } | 314 } |
336 } | 315 } |
337 } | 316 } |
338 return entries_.end(); | 317 return entries_.end(); |
339 } | 318 } |
340 | 319 |
341 // static | 320 // static |
342 bool TabRestoreServiceHelper::ValidateEntry(Entry* entry) { | 321 bool TabRestoreServiceHelper::ValidateEntry(const Entry& entry) { |
343 if (entry->type == TabRestoreService::TAB) | 322 switch (entry.type()) { |
344 return ValidateTab(static_cast<Tab*>(entry)); | 323 case TabRestoreService::TAB: |
345 | 324 return ValidateTab(static_cast<const Tab&>(entry)); |
346 if (entry->type == TabRestoreService::WINDOW) | 325 case TabRestoreService::WINDOW: |
347 return ValidateWindow(static_cast<Window*>(entry)); | 326 return ValidateWindow(static_cast<const Window&>(entry)); |
348 | 327 } |
349 NOTREACHED(); | 328 NOTREACHED(); |
350 return false; | 329 return false; |
351 } | 330 } |
352 | 331 |
353 void TabRestoreServiceHelper::PopulateTab(Tab* tab, | 332 void TabRestoreServiceHelper::PopulateTab(Tab* tab, |
354 int index, | 333 size_t index, |
355 LiveTabContext* context, | 334 LiveTabContext* context, |
356 LiveTab* live_tab) { | 335 LiveTab* live_tab) { |
357 const int pending_index = live_tab->GetPendingEntryIndex(); | 336 const int pending_index = live_tab->GetPendingEntryIndex(); |
358 int entry_count = | 337 int entry_count = |
359 live_tab->IsInitialBlankNavigation() ? 0 : live_tab->GetEntryCount(); | 338 live_tab->IsInitialBlankNavigation() ? 0 : live_tab->GetEntryCount(); |
360 if (entry_count == 0 && pending_index == 0) | 339 if (entry_count == 0 && pending_index == 0) |
361 entry_count++; | 340 entry_count++; |
362 tab->navigations.resize(static_cast<int>(entry_count)); | 341 tab->navigations.resize(static_cast<int>(entry_count)); |
363 for (int i = 0; i < entry_count; ++i) { | 342 for (int i = 0; i < entry_count; ++i) { |
364 SerializedNavigationEntry entry = (i == pending_index) | 343 SerializedNavigationEntry entry = (i == pending_index) |
365 ? live_tab->GetPendingEntry() | 344 ? live_tab->GetPendingEntry() |
366 : live_tab->GetEntryAtIndex(i); | 345 : live_tab->GetEntryAtIndex(i); |
367 tab->navigations[i] = entry; | 346 tab->navigations[i] = entry; |
368 } | 347 } |
369 tab->timestamp = TimeNow(); | 348 tab->timestamp = TimeNow(); |
370 tab->current_navigation_index = live_tab->GetCurrentEntryIndex(); | 349 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; | 350 tab->tabstrip_index = index; |
374 | 351 |
375 tab->extension_app_id = client_->GetExtensionAppIDForTab(live_tab); | 352 tab->extension_app_id = client_->GetExtensionAppIDForTab(live_tab); |
376 | 353 |
377 tab->user_agent_override = live_tab->GetUserAgentOverride(); | 354 tab->user_agent_override = live_tab->GetUserAgentOverride(); |
378 | 355 |
379 tab->platform_data = live_tab->GetPlatformSpecificTabData(); | 356 tab->platform_data = live_tab->GetPlatformSpecificTabData(); |
380 | 357 |
381 // Delegate may be NULL during unit tests. | 358 // Delegate may be NULL during unit tests. |
382 if (context) { | 359 if (context) { |
383 tab->browser_id = context->GetSessionID().id(); | 360 tab->browser_id = context->GetSessionID().id(); |
384 tab->pinned = context->IsTabPinned(tab->tabstrip_index); | 361 tab->pinned = context->IsTabPinned(tab->tabstrip_index); |
385 } | 362 } |
386 } | 363 } |
387 | 364 |
388 LiveTabContext* TabRestoreServiceHelper::RestoreTab( | 365 LiveTabContext* TabRestoreServiceHelper::RestoreTab( |
389 const Tab& tab, | 366 const Tab& tab, |
390 LiveTabContext* context, | 367 LiveTabContext* context, |
391 WindowOpenDisposition disposition, | 368 WindowOpenDisposition disposition, |
392 LiveTab** live_tab) { | 369 LiveTab** live_tab) { |
393 LiveTab* restored_tab; | 370 LiveTab* restored_tab; |
394 if (disposition == CURRENT_TAB && context) { | 371 if (disposition == CURRENT_TAB && context) { |
395 restored_tab = context->ReplaceRestoredTab( | 372 restored_tab = context->ReplaceRestoredTab( |
396 tab.navigations, tab.current_navigation_index, tab.from_last_session, | 373 tab.navigations, tab.current_navigation_index, tab.from_last_session, |
397 tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override); | 374 tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override); |
398 } else { | 375 } else { |
399 // We only respsect the tab's original browser if there's no disposition. | 376 // We only respsect the tab's original browser if there's no disposition. |
400 if (disposition == UNKNOWN && tab.has_browser()) { | 377 if (disposition == UNKNOWN && tab.browser_id) { |
401 context = client_->FindLiveTabContextWithID(tab.browser_id); | 378 context = client_->FindLiveTabContextWithID(tab.browser_id); |
402 } | 379 } |
403 | 380 |
404 int tab_index = -1; | 381 int tab_index = -1; |
405 | 382 |
406 // |context| will be NULL in cases where one isn't already available (eg, | 383 // |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 | 384 // when invoked on Mac OS X with no windows open). In this case, create a |
408 // new browser into which we restore the tabs. | 385 // new browser into which we restore the tabs. |
409 if (context && disposition != NEW_WINDOW) { | 386 if (context && disposition != NEW_WINDOW) { |
410 tab_index = tab.tabstrip_index; | 387 tab_index = tab.tabstrip_index; |
411 } else { | 388 } else { |
412 context = client_->CreateLiveTabContext(std::string()); | 389 context = client_->CreateLiveTabContext(std::string()); |
413 if (tab.has_browser()) | 390 if (tab.browser_id) |
414 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); | 391 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); |
415 } | 392 } |
416 | 393 |
417 // Place the tab at the end if the tab index is no longer valid or | 394 // Place the tab at the end if the tab index is no longer valid or |
418 // we were passed a specific disposition. | 395 // we were passed a specific disposition. |
419 if (tab_index < 0 || tab_index > context->GetTabCount() || | 396 if (tab_index < 0 || tab_index > context->GetTabCount() || |
420 disposition != UNKNOWN) { | 397 disposition != UNKNOWN) { |
421 tab_index = context->GetTabCount(); | 398 tab_index = context->GetTabCount(); |
422 } | 399 } |
423 | 400 |
424 restored_tab = context->AddRestoredTab( | 401 restored_tab = context->AddRestoredTab( |
425 tab.navigations, tab_index, tab.current_navigation_index, | 402 tab.navigations, tab_index, tab.current_navigation_index, |
426 tab.extension_app_id, disposition != NEW_BACKGROUND_TAB, tab.pinned, | 403 tab.extension_app_id, disposition != NEW_BACKGROUND_TAB, tab.pinned, |
427 tab.from_last_session, tab.platform_data.get(), | 404 tab.from_last_session, tab.platform_data.get(), |
428 tab.user_agent_override); | 405 tab.user_agent_override); |
429 restored_tab->LoadIfNecessary(); | 406 restored_tab->LoadIfNecessary(); |
430 } | 407 } |
431 client_->OnTabRestored( | 408 client_->OnTabRestored( |
432 tab.navigations.at(tab.current_navigation_index).virtual_url()); | 409 tab.navigations.at(tab.current_navigation_index).virtual_url()); |
433 if (live_tab) | 410 if (live_tab) |
434 *live_tab = restored_tab; | 411 *live_tab = restored_tab; |
435 | 412 |
436 return context; | 413 return context; |
437 } | 414 } |
438 | 415 |
439 | 416 |
440 bool TabRestoreServiceHelper::ValidateTab(Tab* tab) { | 417 bool TabRestoreServiceHelper::ValidateTab(const Tab& tab) { |
441 if (tab->navigations.empty()) | 418 return !tab.navigations.empty() && |
| 419 tab.current_navigation_index < tab.navigations.size(); |
| 420 } |
| 421 |
| 422 bool TabRestoreServiceHelper::ValidateWindow(const Window& window) { |
| 423 if (window.selected_tab_index >= window.tabs.size()) { |
442 return false; | 424 return false; |
| 425 } |
443 | 426 |
444 tab->current_navigation_index = | 427 for (const auto &tab : window.tabs) { |
445 std::max(0, std::min(tab->current_navigation_index, | 428 if (!ValidateTab(*tab)) { |
446 static_cast<int>(tab->navigations.size()) - 1)); | 429 return false; |
| 430 } |
| 431 } |
447 | 432 |
448 return true; | 433 return true; |
449 } | 434 } |
450 | 435 |
451 bool TabRestoreServiceHelper::ValidateWindow(Window* window) { | 436 bool TabRestoreServiceHelper::IsTabInteresting(const Tab& tab) { |
452 window->selected_tab_index = | 437 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; | 438 return false; |
473 | 439 |
474 return true; | 440 if (tab.navigations.size() > 1) |
| 441 return true; |
| 442 |
| 443 return tab.pinned || |
| 444 tab.navigations.at(0).virtual_url() != client_->GetNewTabURL(); |
475 } | 445 } |
476 | 446 |
477 bool TabRestoreServiceHelper::IsTabInteresting(const Tab* tab) { | 447 bool TabRestoreServiceHelper::IsWindowInteresting(const Window& window) { |
478 if (tab->navigations.empty()) | 448 if (window.tabs.empty()) |
479 return false; | 449 return false; |
480 | 450 |
481 if (tab->navigations.size() > 1) | 451 if (window.tabs.size() > 1) |
482 return true; | 452 return true; |
483 | 453 |
484 return tab->pinned || | 454 return IsTabInteresting(*window.tabs[0]); |
485 tab->navigations.at(0).virtual_url() != client_->GetNewTabURL(); | |
486 } | 455 } |
487 | 456 |
488 bool TabRestoreServiceHelper::IsWindowInteresting(const Window* window) { | 457 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)) | 458 if (!ValidateEntry(entry)) |
500 return false; | 459 return false; |
501 | 460 |
502 if (entry->type == TabRestoreService::TAB) | 461 switch (entry.type()) { |
503 return IsTabInteresting(static_cast<Tab*>(entry)); | 462 case TabRestoreService::TAB: |
504 else if (entry->type == TabRestoreService::WINDOW) | 463 return IsTabInteresting(static_cast<const Tab&>(entry)); |
505 return IsWindowInteresting(static_cast<Window*>(entry)); | 464 case TabRestoreService::WINDOW: |
506 | 465 return IsWindowInteresting(static_cast<const Window&>(entry)); |
| 466 } |
507 NOTREACHED(); | 467 NOTREACHED(); |
508 return false; | 468 return false; |
509 } | 469 } |
510 | 470 |
511 void TabRestoreServiceHelper::UpdateTabBrowserIDs(SessionID::id_type old_id, | 471 void TabRestoreServiceHelper::UpdateTabBrowserIDs(SessionID::id_type old_id, |
512 SessionID::id_type new_id) { | 472 SessionID::id_type new_id) { |
513 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { | 473 for (const auto &entry : entries_) { |
514 Entry* entry = *i; | 474 if (entry->type() == TabRestoreService::TAB) { |
515 if (entry->type == TabRestoreService::TAB) { | 475 auto &tab = static_cast<Tab&>(*entry); |
516 Tab* tab = static_cast<Tab*>(entry); | 476 if (tab.browser_id == old_id) |
517 if (tab->browser_id == old_id) | 477 tab.browser_id = new_id; |
518 tab->browser_id = new_id; | |
519 } | 478 } |
520 } | 479 } |
521 } | 480 } |
522 | 481 |
523 base::Time TabRestoreServiceHelper::TimeNow() const { | 482 base::Time TabRestoreServiceHelper::TimeNow() const { |
524 return time_factory_ ? time_factory_->TimeNow() : base::Time::Now(); | 483 return time_factory_ ? time_factory_->TimeNow() : base::Time::Now(); |
525 } | 484 } |
526 | 485 |
527 } // namespace sessions | 486 } // namespace sessions |
OLD | NEW |