Chromium Code Reviews| 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 |