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/persistent_tab_restore_service.h" | 5 #include "components/sessions/core/persistent_tab_restore_service.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 #include <string.h> | 9 #include <string.h> |
10 #include <utility> | 10 #include <utility> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
15 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/macros.h" | 17 #include "base/macros.h" |
18 #include "base/memory/ptr_util.h" | |
18 #include "base/memory/ref_counted.h" | 19 #include "base/memory/ref_counted.h" |
19 #include "base/memory/scoped_vector.h" | |
20 #include "base/stl_util.h" | 20 #include "base/stl_util.h" |
21 #include "base/task/cancelable_task_tracker.h" | 21 #include "base/task/cancelable_task_tracker.h" |
22 #include "base/time/time.h" | 22 #include "base/time/time.h" |
23 #include "components/sessions/core/base_session_service.h" | 23 #include "components/sessions/core/base_session_service.h" |
24 #include "components/sessions/core/base_session_service_commands.h" | 24 #include "components/sessions/core/base_session_service_commands.h" |
25 #include "components/sessions/core/base_session_service_delegate.h" | 25 #include "components/sessions/core/base_session_service_delegate.h" |
26 #include "components/sessions/core/session_command.h" | 26 #include "components/sessions/core/session_command.h" |
27 #include "components/sessions/core/session_constants.h" | 27 #include "components/sessions/core/session_constants.h" |
28 | 28 |
29 namespace sessions { | 29 namespace sessions { |
30 | 30 |
31 namespace { | 31 namespace { |
32 | 32 |
33 // Only written if the tab is pinned. | 33 // Only written if the tab is pinned. |
34 typedef bool PinnedStatePayload; | 34 typedef bool PinnedStatePayload; |
35 | 35 |
36 typedef int32_t RestoredEntryPayload; | 36 typedef int32_t RestoredEntryPayload; |
37 | 37 |
38 typedef std::map<SessionID::id_type, TabRestoreService::Entry*> IDToEntry; | |
39 | |
40 // Payload used for the start of a tab close. This is the old struct that is | 38 // Payload used for the start of a tab close. This is the old struct that is |
41 // used for backwards compat when it comes to reading the session files. | 39 // used for backwards compat when it comes to reading the session files. |
42 struct SelectedNavigationInTabPayload { | 40 struct SelectedNavigationInTabPayload { |
43 SessionID::id_type id; | 41 SessionID::id_type id; |
44 int32_t index; | 42 int32_t index; |
45 }; | 43 }; |
46 | 44 |
47 // Payload used for the start of a window close. This is the old struct that is | 45 // Payload used for the start of a window close. This is the old struct that is |
48 // used for backwards compat when it comes to reading the session files. This | 46 // used for backwards compat when it comes to reading the session files. This |
49 // struct must be POD, because we memset the contents. | 47 // struct must be POD, because we memset the contents. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
141 tab_restore_service_helper_ = tab_restore_service_helper; | 139 tab_restore_service_helper_ = tab_restore_service_helper; |
142 } | 140 } |
143 | 141 |
144 void LoadTabsFromLastSession(); | 142 void LoadTabsFromLastSession(); |
145 | 143 |
146 void DeleteLastSession(); | 144 void DeleteLastSession(); |
147 | 145 |
148 bool IsLoaded() const; | 146 bool IsLoaded() const; |
149 | 147 |
150 // Creates and add entries to |entries| for each of the windows in |windows|. | 148 // Creates and add entries to |entries| for each of the windows in |windows|. |
151 static void CreateEntriesFromWindows(std::vector<SessionWindow*>* windows, | 149 static void CreateEntriesFromWindows( |
152 std::vector<Entry*>* entries); | 150 std::vector<SessionWindow*>* windows, |
151 std::vector<std::unique_ptr<Entry>>* entries); | |
153 | 152 |
154 void Shutdown(); | 153 void Shutdown(); |
155 | 154 |
156 // Schedules the commands for a window close. | 155 // Schedules the commands for a window close. |
157 void ScheduleCommandsForWindow(const Window& window); | 156 void ScheduleCommandsForWindow(const Window& window); |
158 | 157 |
159 // Schedules the commands for a tab close. |selected_index| gives the index of | 158 // Schedules the commands for a tab close. |selected_index| gives the index of |
160 // the selected navigation. | 159 // the selected navigation. |
161 void ScheduleCommandsForTab(const Tab& tab, int selected_index); | 160 void ScheduleCommandsForTab(const Tab& tab, int selected_index); |
162 | 161 |
(...skipping 19 matching lines...) Expand all Loading... | |
182 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if no | 181 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if no |
183 // valid navigation to persist. | 182 // valid navigation to persist. |
184 int GetSelectedNavigationIndexToPersist(const Tab& tab); | 183 int GetSelectedNavigationIndexToPersist(const Tab& tab); |
185 | 184 |
186 // Invoked when we've loaded the session commands that identify the previously | 185 // Invoked when we've loaded the session commands that identify the previously |
187 // closed tabs. This creates entries, adds them to staging_entries_, and | 186 // closed tabs. This creates entries, adds them to staging_entries_, and |
188 // invokes LoadState. | 187 // invokes LoadState. |
189 void OnGotLastSessionCommands(ScopedVector<SessionCommand> commands); | 188 void OnGotLastSessionCommands(ScopedVector<SessionCommand> commands); |
190 | 189 |
191 // Populates |loaded_entries| with Entries from |commands|. | 190 // Populates |loaded_entries| with Entries from |commands|. |
192 void CreateEntriesFromCommands(const std::vector<SessionCommand*>& commands, | 191 void CreateEntriesFromCommands( |
193 std::vector<Entry*>* loaded_entries); | 192 const std::vector<SessionCommand*>& commands, |
193 std::vector<std::unique_ptr<Entry>>* loaded_entries); | |
194 | 194 |
195 // Validates all entries in |entries|, deleting any with no navigations. This | 195 // Validates all entries in |entries|, deleting any with no navigations. This |
196 // also deletes any entries beyond the max number of entries we can hold. | 196 // also deletes any entries beyond the max number of entries we can hold. |
197 static void ValidateAndDeleteEmptyEntries(std::vector<Entry*>* entries); | 197 static void ValidateAndDeleteEmptyEntries( |
198 std::vector<std::unique_ptr<Entry>>* entries); | |
198 | 199 |
199 // Callback from BaseSessionService when we've received the windows from the | 200 // Callback from BaseSessionService when we've received the windows from the |
200 // previous session. This creates and add entries to |staging_entries_| and | 201 // previous session. This creates and add entries to |staging_entries_| and |
201 // invokes LoadStateChanged. |ignored_active_window| is ignored because we | 202 // invokes LoadStateChanged. |ignored_active_window| is ignored because we |
202 // don't need to restore activation. | 203 // don't need to restore activation. |
203 void OnGotPreviousSession(ScopedVector<SessionWindow> windows, | 204 void OnGotPreviousSession(ScopedVector<SessionWindow> windows, |
204 SessionID::id_type ignored_active_window); | 205 SessionID::id_type ignored_active_window); |
205 | 206 |
206 // Converts a SessionWindow into a Window, returning true on success. We use 0 | 207 // Converts a SessionWindow into a Window, returning true on success. We use 0 |
207 // as the timestamp here since we do not know when the window/tab was closed. | 208 // as the timestamp here since we do not know when the window/tab was closed. |
208 static bool ConvertSessionWindowToWindow(SessionWindow* session_window, | 209 static bool ConvertSessionWindowToWindow(SessionWindow* session_window, |
209 Window* window); | 210 Window* window); |
210 | 211 |
211 // Invoked when previous tabs or session is loaded. If both have finished | 212 // Invoked when previous tabs or session is loaded. If both have finished |
212 // loading the entries in |staging_entries_| are added to entries and | 213 // loading the entries in |staging_entries_| are added to entries and |
213 // observers are notified. | 214 // observers are notified. |
214 void LoadStateChanged(); | 215 void LoadStateChanged(); |
215 | 216 |
216 // If |id_to_entry| contains an entry for |id| the corresponding entry is | |
217 // deleted and removed from both |id_to_entry| and |entries|. This is used | |
218 // when creating entries from the backend file. | |
219 void RemoveEntryByID(SessionID::id_type id, | |
220 IDToEntry* id_to_entry, | |
221 std::vector<TabRestoreService::Entry*>* entries); | |
222 | |
223 private: | 217 private: |
224 // The associated client. | 218 // The associated client. |
225 TabRestoreServiceClient* client_; | 219 TabRestoreServiceClient* client_; |
226 | 220 |
227 std::unique_ptr<BaseSessionService> base_session_service_; | 221 std::unique_ptr<BaseSessionService> base_session_service_; |
228 | 222 |
229 TabRestoreServiceHelper* tab_restore_service_helper_; | 223 TabRestoreServiceHelper* tab_restore_service_helper_; |
230 | 224 |
231 // The number of entries to write. | 225 // The number of entries to write. |
232 int entries_to_write_; | 226 int entries_to_write_; |
233 | 227 |
234 // Number of entries we've written. | 228 // Number of entries we've written. |
235 int entries_written_; | 229 int entries_written_; |
236 | 230 |
237 // Whether we've loaded the last session. | 231 // Whether we've loaded the last session. |
238 int load_state_; | 232 int load_state_; |
239 | 233 |
240 // Results from previously closed tabs/sessions is first added here. When the | 234 // Results from previously closed tabs/sessions is first added here. When the |
241 // results from both us and the session restore service have finished loading | 235 // results from both us and the session restore service have finished loading |
242 // LoadStateChanged is invoked, which adds these entries to entries_. | 236 // LoadStateChanged is invoked, which adds these entries to entries_. |
243 ScopedVector<Entry> staging_entries_; | 237 std::vector<std::unique_ptr<Entry>> staging_entries_; |
244 | 238 |
245 // Used when loading previous tabs/session and open tabs/session. | 239 // Used when loading previous tabs/session and open tabs/session. |
246 base::CancelableTaskTracker cancelable_task_tracker_; | 240 base::CancelableTaskTracker cancelable_task_tracker_; |
247 | 241 |
248 DISALLOW_COPY_AND_ASSIGN(Delegate); | 242 DISALLOW_COPY_AND_ASSIGN(Delegate); |
249 }; | 243 }; |
250 | 244 |
251 PersistentTabRestoreService::Delegate::Delegate(TabRestoreServiceClient* client) | 245 PersistentTabRestoreService::Delegate::Delegate(TabRestoreServiceClient* client) |
252 : client_(client), | 246 : client_(client), |
253 base_session_service_( | 247 base_session_service_( |
(...skipping 26 matching lines...) Expand all Loading... | |
280 base_session_service_->set_pending_reset(true); | 274 base_session_service_->set_pending_reset(true); |
281 } | 275 } |
282 if (to_write_count) { | 276 if (to_write_count) { |
283 // Write the to_write_count most recently added entries out. The most | 277 // Write the to_write_count most recently added entries out. The most |
284 // recently added entry is at the front, so we use a reverse iterator to | 278 // recently added entry is at the front, so we use a reverse iterator to |
285 // write in the order the entries were added. | 279 // write in the order the entries were added. |
286 Entries::const_reverse_iterator i = entries.rbegin(); | 280 Entries::const_reverse_iterator i = entries.rbegin(); |
287 DCHECK(static_cast<size_t>(to_write_count) <= entries.size()); | 281 DCHECK(static_cast<size_t>(to_write_count) <= entries.size()); |
288 std::advance(i, entries.size() - static_cast<int>(to_write_count)); | 282 std::advance(i, entries.size() - static_cast<int>(to_write_count)); |
289 for (; i != entries.rend(); ++i) { | 283 for (; i != entries.rend(); ++i) { |
290 Entry* entry = *i; | 284 Entry* entry = i->get(); |
291 if (entry->type == TAB) { | 285 switch (entry->type) { |
292 Tab* tab = static_cast<Tab*>(entry); | 286 case TAB: { |
293 int selected_index = GetSelectedNavigationIndexToPersist(*tab); | 287 Tab* tab = static_cast<Tab*>(entry); |
294 if (selected_index != -1) | 288 int selected_index = GetSelectedNavigationIndexToPersist(*tab); |
295 ScheduleCommandsForTab(*tab, selected_index); | 289 if (selected_index != -1) |
296 } else { | 290 ScheduleCommandsForTab(*tab, selected_index); |
297 ScheduleCommandsForWindow(*static_cast<Window*>(entry)); | 291 break; |
292 } | |
293 case WINDOW: | |
294 ScheduleCommandsForWindow(*static_cast<Window*>(entry)); | |
295 break; | |
298 } | 296 } |
299 entries_written_++; | 297 entries_written_++; |
300 } | 298 } |
301 } | 299 } |
302 if (base_session_service_->pending_reset()) | 300 if (base_session_service_->pending_reset()) |
303 entries_written_ = 0; | 301 entries_written_ = 0; |
304 } | 302 } |
305 | 303 |
306 void PersistentTabRestoreService::Delegate::OnClearEntries() { | 304 void PersistentTabRestoreService::Delegate::OnClearEntries() { |
307 // Mark all the tabs as closed so that we don't attempt to restore them. | 305 // Mark all the tabs as closed so that we don't attempt to restore them. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 base_session_service_->DeleteLastSession(); | 371 base_session_service_->DeleteLastSession(); |
374 } | 372 } |
375 | 373 |
376 bool PersistentTabRestoreService::Delegate::IsLoaded() const { | 374 bool PersistentTabRestoreService::Delegate::IsLoaded() const { |
377 return !(load_state_ & (NOT_LOADED | LOADING)); | 375 return !(load_state_ & (NOT_LOADED | LOADING)); |
378 } | 376 } |
379 | 377 |
380 // static | 378 // static |
381 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( | 379 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( |
382 std::vector<SessionWindow*>* windows, | 380 std::vector<SessionWindow*>* windows, |
383 std::vector<Entry*>* entries) { | 381 std::vector<std::unique_ptr<Entry>>* entries) { |
384 for (size_t i = 0; i < windows->size(); ++i) { | 382 for (size_t i = 0; i < windows->size(); ++i) { |
385 std::unique_ptr<Window> window(new Window()); | 383 std::unique_ptr<Window> window(new Window()); |
386 if (ConvertSessionWindowToWindow((*windows)[i], window.get())) | 384 if (ConvertSessionWindowToWindow((*windows)[i], window.get())) |
387 entries->push_back(window.release()); | 385 entries->push_back(std::move(window)); |
388 } | 386 } |
389 } | 387 } |
390 | 388 |
391 void PersistentTabRestoreService::Delegate::Shutdown() { | 389 void PersistentTabRestoreService::Delegate::Shutdown() { |
392 base_session_service_->Save(); | 390 base_session_service_->Save(); |
393 } | 391 } |
394 | 392 |
395 void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( | 393 void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( |
396 const Window& window) { | 394 const Window& window) { |
397 DCHECK(!window.tabs.empty()); | 395 DCHECK(!window.tabs.empty()); |
398 int selected_tab = window.selected_tab_index; | 396 int selected_tab = window.selected_tab_index; |
399 int valid_tab_count = 0; | 397 int valid_tab_count = 0; |
400 int real_selected_tab = selected_tab; | 398 int real_selected_tab = selected_tab; |
401 for (size_t i = 0; i < window.tabs.size(); ++i) { | 399 for (size_t i = 0; i < window.tabs.size(); ++i) { |
402 if (GetSelectedNavigationIndexToPersist(window.tabs[i]) != -1) { | 400 if (GetSelectedNavigationIndexToPersist(*window.tabs[i]) != -1) { |
403 valid_tab_count++; | 401 valid_tab_count++; |
404 } else if (static_cast<int>(i) < selected_tab) { | 402 } else if (static_cast<int>(i) < selected_tab) { |
405 real_selected_tab--; | 403 real_selected_tab--; |
406 } | 404 } |
407 } | 405 } |
408 if (valid_tab_count == 0) | 406 if (valid_tab_count == 0) |
409 return; // No tabs to persist. | 407 return; // No tabs to persist. |
410 | 408 |
411 base_session_service_->ScheduleCommand(CreateWindowCommand( | 409 base_session_service_->ScheduleCommand(CreateWindowCommand( |
412 window.id, std::min(real_selected_tab, valid_tab_count - 1), | 410 window.id, std::min(real_selected_tab, valid_tab_count - 1), |
413 valid_tab_count, window.timestamp)); | 411 valid_tab_count, window.timestamp)); |
414 | 412 |
415 if (!window.app_name.empty()) { | 413 if (!window.app_name.empty()) { |
416 base_session_service_->ScheduleCommand(CreateSetWindowAppNameCommand( | 414 base_session_service_->ScheduleCommand(CreateSetWindowAppNameCommand( |
417 kCommandSetWindowAppName, window.id, window.app_name)); | 415 kCommandSetWindowAppName, window.id, window.app_name)); |
418 } | 416 } |
419 | 417 |
420 for (size_t i = 0; i < window.tabs.size(); ++i) { | 418 for (size_t i = 0; i < window.tabs.size(); ++i) { |
421 int selected_index = GetSelectedNavigationIndexToPersist(window.tabs[i]); | 419 int selected_index = GetSelectedNavigationIndexToPersist(*window.tabs[i]); |
422 if (selected_index != -1) | 420 if (selected_index != -1) |
423 ScheduleCommandsForTab(window.tabs[i], selected_index); | 421 ScheduleCommandsForTab(*window.tabs[i], selected_index); |
424 } | 422 } |
425 } | 423 } |
426 | 424 |
427 void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( | 425 void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( |
428 const Tab& tab, | 426 const Tab& tab, |
429 int selected_index) { | 427 int selected_index) { |
430 const std::vector<SerializedNavigationEntry>& navigations = tab.navigations; | 428 const std::vector<SerializedNavigationEntry>& navigations = tab.navigations; |
431 int max_index = static_cast<int>(navigations.size()); | 429 int max_index = static_cast<int>(navigations.size()); |
432 | 430 |
433 // Determine the first navigation we'll persist. | 431 // Determine the first navigation we'll persist. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
548 !client_->ShouldTrackURLForRestore( | 546 !client_->ShouldTrackURLForRestore( |
549 navigations[selected_index].virtual_url())) { | 547 navigations[selected_index].virtual_url())) { |
550 selected_index++; | 548 selected_index++; |
551 } | 549 } |
552 | 550 |
553 return (selected_index == max_index) ? -1 : selected_index; | 551 return (selected_index == max_index) ? -1 : selected_index; |
554 } | 552 } |
555 | 553 |
556 void PersistentTabRestoreService::Delegate::OnGotLastSessionCommands( | 554 void PersistentTabRestoreService::Delegate::OnGotLastSessionCommands( |
557 ScopedVector<SessionCommand> commands) { | 555 ScopedVector<SessionCommand> commands) { |
558 std::vector<Entry*> entries; | 556 std::vector<std::unique_ptr<Entry>> entries; |
559 CreateEntriesFromCommands(commands.get(), &entries); | 557 CreateEntriesFromCommands(commands.get(), &entries); |
560 // Closed tabs always go to the end. | 558 // Closed tabs always go to the end. |
561 staging_entries_.insert(staging_entries_.end(), entries.begin(), | 559 staging_entries_.insert(staging_entries_.end(), |
562 entries.end()); | 560 make_move_iterator(entries.begin()), |
561 make_move_iterator(entries.end())); | |
563 load_state_ |= LOADED_LAST_TABS; | 562 load_state_ |= LOADED_LAST_TABS; |
564 LoadStateChanged(); | 563 LoadStateChanged(); |
565 } | 564 } |
566 | 565 |
566 namespace { | |
567 | |
568 class RemoveByIDIndex { | |
sky
2016/08/04 16:34:39
This code is far too subtle. Please document it al
Sidney San MartÃn
2016/08/04 17:04:50
Can you think of a simpler way to model this? I ma
sky
2016/08/04 19:09:52
How about changing Entries to a std::vector? TabRe
Sidney San MartÃn
2016/08/04 20:17:19
I like this idea in general, but it doesn't solve
sky
2016/08/04 22:57:12
I prefer the old code, while not as efficient it's
Sidney San MartÃn
2016/08/09 04:10:52
OK, agreed. I still want to find a simple and effi
| |
569 std::unordered_map<SessionID::id_type, std::function<void()>> index_; | |
sky
2016/08/04 16:34:39
public section is first, then private.
| |
570 | |
571 public: | |
572 template <typename T> | |
573 void index_back(T* collection) { | |
574 auto entry = &collection->back(); | |
575 index_[(*entry)->id] = [=]() { | |
sky
2016/08/04 16:34:39
Oy, this is hard to parse. Please be explicit abou
| |
576 auto it = std::find(collection->begin(), collection->end(), *entry); | |
577 if (it != collection->end()) { | |
sky
2016/08/04 16:34:39
no {}
| |
578 collection->erase(it); | |
579 } | |
580 }; | |
581 } | |
582 | |
583 void remove(SessionID::id_type id) { | |
584 auto it = index_.find(id); | |
585 if (it != index_.end()) { | |
sky
2016/08/04 16:34:39
no {}
| |
586 it->second(); | |
sky
2016/08/04 16:34:39
This is subtle and woth a comment.
| |
587 } | |
588 } | |
589 }; | |
590 | |
591 } // namespace | |
592 | |
567 void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( | 593 void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( |
568 const std::vector<SessionCommand*>& commands, | 594 const std::vector<SessionCommand*>& commands, |
569 std::vector<Entry*>* loaded_entries) { | 595 std::vector<std::unique_ptr<Entry>>* loaded_entries) { |
570 if (tab_restore_service_helper_->entries().size() == kMaxEntries) | 596 if (tab_restore_service_helper_->entries().size() == kMaxEntries) |
571 return; | 597 return; |
572 | 598 |
573 // Iterate through the commands populating entries and id_to_entry. | 599 // Iterate through the commands populating entries and remove_by_id. |
574 ScopedVector<Entry> entries; | 600 std::vector<std::unique_ptr<Entry>> entries; |
575 IDToEntry id_to_entry; | 601 RemoveByIDIndex remove_by_id; |
576 // If non-null we're processing the navigations of this tab. | 602 // If non-null we're processing the navigations of this tab. |
577 Tab* current_tab = NULL; | 603 Tab* current_tab = nullptr; |
578 // If non-null we're processing the tabs of this window. | 604 // If non-null we're processing the tabs of this window. |
579 Window* current_window = NULL; | 605 Window* current_window = nullptr; |
580 // If > 0, we've gotten a window command but not all the tabs yet. | 606 // If > 0, we've gotten a window command but not all the tabs yet. |
581 int pending_window_tabs = 0; | 607 int pending_window_tabs = 0; |
582 for (std::vector<SessionCommand*>::const_iterator i = commands.begin(); | 608 for (std::vector<SessionCommand*>::const_iterator i = commands.begin(); |
583 i != commands.end(); ++i) { | 609 i != commands.end(); ++i) { |
584 const SessionCommand& command = *(*i); | 610 const SessionCommand& command = *(*i); |
585 switch (command.id()) { | 611 switch (command.id()) { |
586 case kCommandRestoredEntry: { | 612 case kCommandRestoredEntry: { |
587 if (pending_window_tabs > 0) { | 613 if (pending_window_tabs > 0) { |
588 // Should never receive a restored command while waiting for all the | 614 // Should never receive a restored command while waiting for all the |
589 // tabs in a window. | 615 // tabs in a window. |
590 return; | 616 return; |
591 } | 617 } |
592 | 618 |
593 current_tab = NULL; | 619 current_tab = nullptr; |
594 current_window = NULL; | 620 current_window = nullptr; |
595 | 621 |
596 RestoredEntryPayload payload; | 622 RestoredEntryPayload payload; |
597 if (!command.GetPayload(&payload, sizeof(payload))) | 623 if (!command.GetPayload(&payload, sizeof(payload))) |
598 return; | 624 return; |
599 RemoveEntryByID(payload, &id_to_entry, &(entries.get())); | 625 remove_by_id.remove(payload); |
600 break; | 626 break; |
601 } | 627 } |
602 | 628 |
603 case kCommandWindow: { | 629 case kCommandWindow: { |
604 WindowPayload2 payload; | 630 WindowPayload2 payload; |
605 if (pending_window_tabs > 0) { | 631 if (pending_window_tabs > 0) { |
606 // Should never receive a window command while waiting for all the | 632 // Should never receive a window command while waiting for all the |
607 // tabs in a window. | 633 // tabs in a window. |
608 return; | 634 return; |
609 } | 635 } |
(...skipping 13 matching lines...) Expand all Loading... | |
623 // unknown timestamp. | 649 // unknown timestamp. |
624 payload.timestamp = 0; | 650 payload.timestamp = 0; |
625 } | 651 } |
626 | 652 |
627 pending_window_tabs = payload.num_tabs; | 653 pending_window_tabs = payload.num_tabs; |
628 if (pending_window_tabs <= 0) { | 654 if (pending_window_tabs <= 0) { |
629 // Should always have at least 1 tab. Likely indicates corruption. | 655 // Should always have at least 1 tab. Likely indicates corruption. |
630 return; | 656 return; |
631 } | 657 } |
632 | 658 |
633 RemoveEntryByID(payload.window_id, &id_to_entry, &(entries.get())); | 659 remove_by_id.remove(payload.window_id); |
634 | 660 |
635 current_window = new Window(); | 661 entries.push_back(base::MakeUnique<Window>()); |
662 current_window = static_cast<Window*>(entries.back().get()); | |
636 current_window->selected_tab_index = payload.selected_tab_index; | 663 current_window->selected_tab_index = payload.selected_tab_index; |
637 current_window->timestamp = | 664 current_window->timestamp = |
638 base::Time::FromInternalValue(payload.timestamp); | 665 base::Time::FromInternalValue(payload.timestamp); |
639 entries.push_back(current_window); | 666 remove_by_id.index_back(&entries); |
640 id_to_entry[payload.window_id] = current_window; | |
641 break; | 667 break; |
642 } | 668 } |
643 | 669 |
644 case kCommandSelectedNavigationInTab: { | 670 case kCommandSelectedNavigationInTab: { |
645 SelectedNavigationInTabPayload2 payload; | 671 SelectedNavigationInTabPayload2 payload; |
646 if (!command.GetPayload(&payload, sizeof(payload))) { | 672 if (!command.GetPayload(&payload, sizeof(payload))) { |
647 SelectedNavigationInTabPayload old_payload; | 673 SelectedNavigationInTabPayload old_payload; |
648 if (!command.GetPayload(&old_payload, sizeof(old_payload))) | 674 if (!command.GetPayload(&old_payload, sizeof(old_payload))) |
649 return; | 675 return; |
650 payload.id = old_payload.id; | 676 payload.id = old_payload.id; |
651 payload.index = old_payload.index; | 677 payload.index = old_payload.index; |
652 // Since we don't have a time use time 0 which is used to mark as an | 678 // Since we don't have a time use time 0 which is used to mark as an |
653 // unknown timestamp. | 679 // unknown timestamp. |
654 payload.timestamp = 0; | 680 payload.timestamp = 0; |
655 } | 681 } |
656 | 682 |
657 if (pending_window_tabs > 0) { | 683 if (pending_window_tabs > 0) { |
658 if (!current_window) { | 684 if (!current_window) { |
659 // We should have created a window already. | 685 // We should have created a window already. |
660 NOTREACHED(); | 686 NOTREACHED(); |
661 return; | 687 return; |
662 } | 688 } |
663 current_window->tabs.resize(current_window->tabs.size() + 1); | 689 current_window->tabs.push_back(base::MakeUnique<Tab>()); |
664 current_tab = &(current_window->tabs.back()); | 690 current_tab = current_window->tabs.back().get(); |
665 if (--pending_window_tabs == 0) | 691 if (--pending_window_tabs == 0) |
666 current_window = NULL; | 692 current_window = nullptr; |
667 } else { | 693 } else { |
668 RemoveEntryByID(payload.id, &id_to_entry, &(entries.get())); | 694 remove_by_id.remove(payload.id); |
669 current_tab = new Tab(); | 695 entries.push_back(base::MakeUnique<Tab>()); |
670 id_to_entry[payload.id] = current_tab; | 696 remove_by_id.index_back(&entries); |
697 current_tab = static_cast<Tab*>(entries.back().get()); | |
671 current_tab->timestamp = | 698 current_tab->timestamp = |
672 base::Time::FromInternalValue(payload.timestamp); | 699 base::Time::FromInternalValue(payload.timestamp); |
673 entries.push_back(current_tab); | |
674 } | 700 } |
675 current_tab->current_navigation_index = payload.index; | 701 current_tab->current_navigation_index = payload.index; |
676 break; | 702 break; |
677 } | 703 } |
678 | 704 |
679 case kCommandUpdateTabNavigation: { | 705 case kCommandUpdateTabNavigation: { |
680 if (!current_tab) { | 706 if (!current_tab) { |
681 // Should be in a tab when we get this. | 707 // Should be in a tab when we get this. |
682 return; | 708 return; |
683 } | 709 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
750 break; | 776 break; |
751 } | 777 } |
752 | 778 |
753 default: | 779 default: |
754 // Unknown type, usually indicates corruption of file. Ignore it. | 780 // Unknown type, usually indicates corruption of file. Ignore it. |
755 return; | 781 return; |
756 } | 782 } |
757 } | 783 } |
758 | 784 |
759 // If there was corruption some of the entries won't be valid. | 785 // If there was corruption some of the entries won't be valid. |
760 ValidateAndDeleteEmptyEntries(&(entries.get())); | 786 ValidateAndDeleteEmptyEntries(&entries); |
761 | 787 |
762 loaded_entries->swap(entries.get()); | 788 loaded_entries->swap(entries); |
763 } | 789 } |
764 | 790 |
765 // static | 791 // static |
766 void PersistentTabRestoreService::Delegate::ValidateAndDeleteEmptyEntries( | 792 void PersistentTabRestoreService::Delegate::ValidateAndDeleteEmptyEntries( |
767 std::vector<Entry*>* entries) { | 793 std::vector<std::unique_ptr<Entry>>* entries) { |
768 std::vector<Entry*> valid_entries; | 794 std::vector<std::unique_ptr<Entry>> valid_entries; |
769 std::vector<Entry*> invalid_entries; | |
770 | 795 |
771 // Iterate from the back so that we keep the most recently closed entries. | 796 // Iterate from the back so that we keep the most recently closed entries. |
772 for (std::vector<Entry*>::reverse_iterator i = entries->rbegin(); | 797 for (auto i = entries->rbegin(); i != entries->rend(); ++i) { |
773 i != entries->rend(); ++i) { | 798 if (TabRestoreServiceHelper::ValidateEntry(**i)) |
774 if (TabRestoreServiceHelper::ValidateEntry(*i)) | 799 valid_entries.push_back(std::move(*i)); |
775 valid_entries.push_back(*i); | |
776 else | |
777 invalid_entries.push_back(*i); | |
778 } | 800 } |
779 // NOTE: at this point the entries are ordered with newest at the front. | 801 // NOTE: at this point the entries are ordered with newest at the front. |
780 entries->swap(valid_entries); | 802 entries->swap(valid_entries); |
781 | |
782 // Delete the remaining entries. | |
783 STLDeleteElements(&invalid_entries); | |
784 } | 803 } |
785 | 804 |
786 void PersistentTabRestoreService::Delegate::OnGotPreviousSession( | 805 void PersistentTabRestoreService::Delegate::OnGotPreviousSession( |
787 ScopedVector<SessionWindow> windows, | 806 ScopedVector<SessionWindow> windows, |
788 SessionID::id_type ignored_active_window) { | 807 SessionID::id_type ignored_active_window) { |
789 std::vector<Entry*> entries; | 808 std::vector<std::unique_ptr<Entry>> entries; |
790 CreateEntriesFromWindows(&windows.get(), &entries); | 809 CreateEntriesFromWindows(&windows.get(), &entries); |
791 // Previous session tabs go first. | 810 // Previous session tabs go first. |
792 staging_entries_.insert(staging_entries_.begin(), entries.begin(), | 811 staging_entries_.insert(staging_entries_.begin(), |
793 entries.end()); | 812 make_move_iterator(entries.begin()), |
813 make_move_iterator(entries.end())); | |
794 load_state_ |= LOADED_LAST_SESSION; | 814 load_state_ |= LOADED_LAST_SESSION; |
795 LoadStateChanged(); | 815 LoadStateChanged(); |
796 } | 816 } |
797 | 817 |
798 bool PersistentTabRestoreService::Delegate::ConvertSessionWindowToWindow( | 818 bool PersistentTabRestoreService::Delegate::ConvertSessionWindowToWindow( |
799 SessionWindow* session_window, | 819 SessionWindow* session_window, |
800 Window* window) { | 820 Window* window) { |
801 for (size_t i = 0; i < session_window->tabs.size(); ++i) { | 821 for (size_t i = 0; i < session_window->tabs.size(); ++i) { |
802 if (!session_window->tabs[i]->navigations.empty()) { | 822 if (!session_window->tabs[i]->navigations.empty()) { |
803 window->tabs.resize(window->tabs.size() + 1); | 823 window->tabs.push_back(base::MakeUnique<Tab>()); |
804 Tab& tab = window->tabs.back(); | 824 Tab& tab = *window->tabs.back(); |
805 tab.pinned = session_window->tabs[i]->pinned; | 825 tab.pinned = session_window->tabs[i]->pinned; |
806 tab.navigations.swap(session_window->tabs[i]->navigations); | 826 tab.navigations.swap(session_window->tabs[i]->navigations); |
807 tab.current_navigation_index = | 827 tab.current_navigation_index = |
808 session_window->tabs[i]->current_navigation_index; | 828 session_window->tabs[i]->current_navigation_index; |
809 tab.extension_app_id = session_window->tabs[i]->extension_app_id; | 829 tab.extension_app_id = session_window->tabs[i]->extension_app_id; |
810 tab.timestamp = base::Time(); | 830 tab.timestamp = base::Time(); |
811 } | 831 } |
812 } | 832 } |
813 if (window->tabs.empty()) | 833 if (window->tabs.empty()) |
814 return false; | 834 return false; |
(...skipping 28 matching lines...) Expand all Loading... | |
843 // kMaxEntries. | 863 // kMaxEntries. |
844 int surplus = kMaxEntries - entries.size(); | 864 int surplus = kMaxEntries - entries.size(); |
845 CHECK_LE(0, surplus); | 865 CHECK_LE(0, surplus); |
846 CHECK_GE(static_cast<int>(staging_entries_.size()), surplus); | 866 CHECK_GE(static_cast<int>(staging_entries_.size()), surplus); |
847 staging_entries_.erase( | 867 staging_entries_.erase( |
848 staging_entries_.begin() + (kMaxEntries - entries.size()), | 868 staging_entries_.begin() + (kMaxEntries - entries.size()), |
849 staging_entries_.end()); | 869 staging_entries_.end()); |
850 } | 870 } |
851 | 871 |
852 // And add them. | 872 // And add them. |
853 for (size_t i = 0; i < staging_entries_.size(); ++i) { | 873 for (auto& staging_entry : staging_entries_) { |
854 staging_entries_[i]->from_last_session = true; | 874 staging_entry->from_last_session = true; |
855 tab_restore_service_helper_->AddEntry(staging_entries_[i], false, false); | 875 tab_restore_service_helper_->AddEntry(std::move(staging_entry), false, |
876 false); | |
856 } | 877 } |
857 | 878 |
858 // AddEntry takes ownership of the entry, need to clear out entries so that | 879 staging_entries_.clear(); |
859 // it doesn't delete them. | 880 entries_to_write_ = 0; |
860 staging_entries_.weak_clear(); | |
861 | |
862 // Make it so we rewrite all the tabs. We need to do this otherwise we won't | |
863 // correctly write out the entries when Save is invoked (Save starts from | |
864 // the front, not the end and we just added the entries to the end). | |
865 entries_to_write_ = staging_entries_.size(); | |
866 | 881 |
867 tab_restore_service_helper_->PruneEntries(); | 882 tab_restore_service_helper_->PruneEntries(); |
868 tab_restore_service_helper_->NotifyTabsChanged(); | 883 tab_restore_service_helper_->NotifyTabsChanged(); |
869 | 884 |
870 tab_restore_service_helper_->NotifyLoaded(); | 885 tab_restore_service_helper_->NotifyLoaded(); |
871 } | 886 } |
872 | 887 |
873 void PersistentTabRestoreService::Delegate::RemoveEntryByID( | |
874 SessionID::id_type id, | |
875 IDToEntry* id_to_entry, | |
876 std::vector<TabRestoreService::Entry*>* entries) { | |
877 // Look for the entry in the map. If it is present, erase it from both | |
878 // collections and return. | |
879 IDToEntry::iterator i = id_to_entry->find(id); | |
880 if (i != id_to_entry->end()) { | |
881 entries->erase(std::find(entries->begin(), entries->end(), i->second)); | |
882 delete i->second; | |
883 id_to_entry->erase(i); | |
884 return; | |
885 } | |
886 | |
887 // Otherwise, loop over all items in the map and see if any of the Windows | |
888 // have Tabs with the |id|. | |
889 for (IDToEntry::iterator i = id_to_entry->begin(); i != id_to_entry->end(); | |
890 ++i) { | |
891 if (i->second->type == TabRestoreService::WINDOW) { | |
892 TabRestoreService::Window* window = | |
893 static_cast<TabRestoreService::Window*>(i->second); | |
894 std::vector<TabRestoreService::Tab>::iterator j = window->tabs.begin(); | |
895 for ( ; j != window->tabs.end(); ++j) { | |
896 // If the ID matches one of this window's tabs, remove it from the | |
897 // list. | |
898 if ((*j).id == id) { | |
899 window->tabs.erase(j); | |
900 return; | |
901 } | |
902 } | |
903 } | |
904 } | |
905 } | |
906 | |
907 // PersistentTabRestoreService ------------------------------------------------- | 888 // PersistentTabRestoreService ------------------------------------------------- |
908 | 889 |
909 PersistentTabRestoreService::PersistentTabRestoreService( | 890 PersistentTabRestoreService::PersistentTabRestoreService( |
910 std::unique_ptr<TabRestoreServiceClient> client, | 891 std::unique_ptr<TabRestoreServiceClient> client, |
911 TimeFactory* time_factory) | 892 TimeFactory* time_factory) |
912 : client_(std::move(client)), | 893 : client_(std::move(client)), |
913 delegate_(new Delegate(client_.get())), | 894 delegate_(new Delegate(client_.get())), |
914 helper_(this, delegate_.get(), client_.get(), time_factory) { | 895 helper_(this, delegate_.get(), client_.get(), time_factory) { |
915 delegate_->set_tab_restore_service_helper(&helper_); | 896 delegate_->set_tab_restore_service_helper(&helper_); |
916 } | 897 } |
(...skipping 29 matching lines...) Expand all Loading... | |
946 | 927 |
947 const TabRestoreService::Entries& PersistentTabRestoreService::entries() const { | 928 const TabRestoreService::Entries& PersistentTabRestoreService::entries() const { |
948 return helper_.entries(); | 929 return helper_.entries(); |
949 } | 930 } |
950 | 931 |
951 std::vector<LiveTab*> PersistentTabRestoreService::RestoreMostRecentEntry( | 932 std::vector<LiveTab*> PersistentTabRestoreService::RestoreMostRecentEntry( |
952 LiveTabContext* context) { | 933 LiveTabContext* context) { |
953 return helper_.RestoreMostRecentEntry(context); | 934 return helper_.RestoreMostRecentEntry(context); |
954 } | 935 } |
955 | 936 |
956 TabRestoreService::Tab* PersistentTabRestoreService::RemoveTabEntryById( | 937 std::unique_ptr<TabRestoreService::Tab> |
957 SessionID::id_type id) { | 938 PersistentTabRestoreService::RemoveTabEntryById(SessionID::id_type id) { |
958 return helper_.RemoveTabEntryById(id); | 939 return helper_.RemoveTabEntryById(id); |
959 } | 940 } |
960 | 941 |
961 std::vector<LiveTab*> PersistentTabRestoreService::RestoreEntryById( | 942 std::vector<LiveTab*> PersistentTabRestoreService::RestoreEntryById( |
962 LiveTabContext* context, | 943 LiveTabContext* context, |
963 SessionID::id_type id, | 944 SessionID::id_type id, |
964 WindowOpenDisposition disposition) { | 945 WindowOpenDisposition disposition) { |
965 return helper_.RestoreEntryById(context, id, disposition); | 946 return helper_.RestoreEntryById(context, id, disposition); |
966 } | 947 } |
967 | 948 |
(...skipping 15 matching lines...) Expand all Loading... | |
983 | 964 |
984 TabRestoreService::Entries* PersistentTabRestoreService::mutable_entries() { | 965 TabRestoreService::Entries* PersistentTabRestoreService::mutable_entries() { |
985 return &helper_.entries_; | 966 return &helper_.entries_; |
986 } | 967 } |
987 | 968 |
988 void PersistentTabRestoreService::PruneEntries() { | 969 void PersistentTabRestoreService::PruneEntries() { |
989 helper_.PruneEntries(); | 970 helper_.PruneEntries(); |
990 } | 971 } |
991 | 972 |
992 } // namespace sessions | 973 } // namespace sessions |
OLD | NEW |