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

Side by Side Diff: components/sessions/core/tab_restore_service_helper.cc

Issue 2200993004: Make TabRestoreService::Entry noncopyable and fix up surrounding code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@tab-test-cleanup
Patch Set: Eliminate a use-after-free, Windows build fix Created 4 years, 4 months 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
OLDNEW
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
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 }
Sidney San Martín 2016/08/04 04:24:57 I had a use-after free here, so I'm using a block
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698