| 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 const SessionCommand::id_type kCommandSetExtensionAppID = 6; | 102 const SessionCommand::id_type kCommandSetExtensionAppID = 6; |
| 105 const SessionCommand::id_type kCommandSetWindowAppName = 7; | 103 const SessionCommand::id_type kCommandSetWindowAppName = 7; |
| 106 const SessionCommand::id_type kCommandSetTabUserAgentOverride = 8; | 104 const SessionCommand::id_type kCommandSetTabUserAgentOverride = 8; |
| 107 | 105 |
| 108 // Number of entries (not commands) before we clobber the file and write | 106 // Number of entries (not commands) before we clobber the file and write |
| 109 // everything. | 107 // everything. |
| 110 const int kEntriesPerReset = 40; | 108 const int kEntriesPerReset = 40; |
| 111 | 109 |
| 112 const size_t kMaxEntries = TabRestoreServiceHelper::kMaxEntries; | 110 const size_t kMaxEntries = TabRestoreServiceHelper::kMaxEntries; |
| 113 | 111 |
| 112 void RemoveEntryByID( |
| 113 SessionID::id_type id, |
| 114 std::vector<std::unique_ptr<TabRestoreService::Entry>>* entries) { |
| 115 // Look for the entry in the top-level collection. |
| 116 for (auto it = entries->begin(); it != entries->end(); ++it) { |
| 117 TabRestoreService::Entry& entry = **it; |
| 118 // Erase it if it's our target. |
| 119 if (entry.id == id) { |
| 120 entries->erase(it); |
| 121 return; |
| 122 } |
| 123 // If this entry is a window, look through its tabs. |
| 124 if (entry.type == TabRestoreService::WINDOW) { |
| 125 auto& window = static_cast<TabRestoreService::Window&>(entry); |
| 126 for (auto it = window.tabs.begin(); it != window.tabs.end(); ++it) { |
| 127 const TabRestoreService::Tab& tab = **it; |
| 128 // Erase it if it's our target. |
| 129 if (tab.id == id) { |
| 130 window.tabs.erase(it); |
| 131 return; |
| 132 } |
| 133 } |
| 134 } |
| 135 } |
| 136 } |
| 137 |
| 114 } // namespace | 138 } // namespace |
| 115 | 139 |
| 116 // PersistentTabRestoreService::Delegate --------------------------------------- | 140 // PersistentTabRestoreService::Delegate --------------------------------------- |
| 117 | 141 |
| 118 // This restore service will create and own a BaseSessionService and implement | 142 // This restore service will create and own a BaseSessionService and implement |
| 119 // the required BaseSessionServiceDelegate. | 143 // the required BaseSessionServiceDelegate. |
| 120 class PersistentTabRestoreService::Delegate | 144 class PersistentTabRestoreService::Delegate |
| 121 : public BaseSessionServiceDelegate, | 145 : public BaseSessionServiceDelegate, |
| 122 public TabRestoreServiceHelper::Observer { | 146 public TabRestoreServiceHelper::Observer { |
| 123 public: | 147 public: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 141 tab_restore_service_helper_ = tab_restore_service_helper; | 165 tab_restore_service_helper_ = tab_restore_service_helper; |
| 142 } | 166 } |
| 143 | 167 |
| 144 void LoadTabsFromLastSession(); | 168 void LoadTabsFromLastSession(); |
| 145 | 169 |
| 146 void DeleteLastSession(); | 170 void DeleteLastSession(); |
| 147 | 171 |
| 148 bool IsLoaded() const; | 172 bool IsLoaded() const; |
| 149 | 173 |
| 150 // Creates and add entries to |entries| for each of the windows in |windows|. | 174 // Creates and add entries to |entries| for each of the windows in |windows|. |
| 151 static void CreateEntriesFromWindows(std::vector<SessionWindow*>* windows, | 175 static void CreateEntriesFromWindows( |
| 152 std::vector<Entry*>* entries); | 176 std::vector<SessionWindow*>* windows, |
| 177 std::vector<std::unique_ptr<Entry>>* entries); |
| 153 | 178 |
| 154 void Shutdown(); | 179 void Shutdown(); |
| 155 | 180 |
| 156 // Schedules the commands for a window close. | 181 // Schedules the commands for a window close. |
| 157 void ScheduleCommandsForWindow(const Window& window); | 182 void ScheduleCommandsForWindow(const Window& window); |
| 158 | 183 |
| 159 // Schedules the commands for a tab close. |selected_index| gives the index of | 184 // Schedules the commands for a tab close. |selected_index| gives the index of |
| 160 // the selected navigation. | 185 // the selected navigation. |
| 161 void ScheduleCommandsForTab(const Tab& tab, int selected_index); | 186 void ScheduleCommandsForTab(const Tab& tab, int selected_index); |
| 162 | 187 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 182 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if no | 207 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if no |
| 183 // valid navigation to persist. | 208 // valid navigation to persist. |
| 184 int GetSelectedNavigationIndexToPersist(const Tab& tab); | 209 int GetSelectedNavigationIndexToPersist(const Tab& tab); |
| 185 | 210 |
| 186 // Invoked when we've loaded the session commands that identify the previously | 211 // Invoked when we've loaded the session commands that identify the previously |
| 187 // closed tabs. This creates entries, adds them to staging_entries_, and | 212 // closed tabs. This creates entries, adds them to staging_entries_, and |
| 188 // invokes LoadState. | 213 // invokes LoadState. |
| 189 void OnGotLastSessionCommands(ScopedVector<SessionCommand> commands); | 214 void OnGotLastSessionCommands(ScopedVector<SessionCommand> commands); |
| 190 | 215 |
| 191 // Populates |loaded_entries| with Entries from |commands|. | 216 // Populates |loaded_entries| with Entries from |commands|. |
| 192 void CreateEntriesFromCommands(const std::vector<SessionCommand*>& commands, | 217 void CreateEntriesFromCommands( |
| 193 std::vector<Entry*>* loaded_entries); | 218 const std::vector<SessionCommand*>& commands, |
| 219 std::vector<std::unique_ptr<Entry>>* loaded_entries); |
| 194 | 220 |
| 195 // Validates all entries in |entries|, deleting any with no navigations. This | 221 // 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. | 222 // also deletes any entries beyond the max number of entries we can hold. |
| 197 static void ValidateAndDeleteEmptyEntries(std::vector<Entry*>* entries); | 223 static void ValidateAndDeleteEmptyEntries( |
| 224 std::vector<std::unique_ptr<Entry>>* entries); |
| 198 | 225 |
| 199 // Callback from BaseSessionService when we've received the windows from the | 226 // Callback from BaseSessionService when we've received the windows from the |
| 200 // previous session. This creates and add entries to |staging_entries_| and | 227 // previous session. This creates and add entries to |staging_entries_| and |
| 201 // invokes LoadStateChanged. |ignored_active_window| is ignored because we | 228 // invokes LoadStateChanged. |ignored_active_window| is ignored because we |
| 202 // don't need to restore activation. | 229 // don't need to restore activation. |
| 203 void OnGotPreviousSession(ScopedVector<SessionWindow> windows, | 230 void OnGotPreviousSession(ScopedVector<SessionWindow> windows, |
| 204 SessionID::id_type ignored_active_window); | 231 SessionID::id_type ignored_active_window); |
| 205 | 232 |
| 206 // Converts a SessionWindow into a Window, returning true on success. We use 0 | 233 // 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. | 234 // as the timestamp here since we do not know when the window/tab was closed. |
| 208 static bool ConvertSessionWindowToWindow(SessionWindow* session_window, | 235 static bool ConvertSessionWindowToWindow(SessionWindow* session_window, |
| 209 Window* window); | 236 Window* window); |
| 210 | 237 |
| 211 // Invoked when previous tabs or session is loaded. If both have finished | 238 // Invoked when previous tabs or session is loaded. If both have finished |
| 212 // loading the entries in |staging_entries_| are added to entries and | 239 // loading the entries in |staging_entries_| are added to entries and |
| 213 // observers are notified. | 240 // observers are notified. |
| 214 void LoadStateChanged(); | 241 void LoadStateChanged(); |
| 215 | 242 |
| 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: | 243 private: |
| 224 // The associated client. | 244 // The associated client. |
| 225 TabRestoreServiceClient* client_; | 245 TabRestoreServiceClient* client_; |
| 226 | 246 |
| 227 std::unique_ptr<BaseSessionService> base_session_service_; | 247 std::unique_ptr<BaseSessionService> base_session_service_; |
| 228 | 248 |
| 229 TabRestoreServiceHelper* tab_restore_service_helper_; | 249 TabRestoreServiceHelper* tab_restore_service_helper_; |
| 230 | 250 |
| 231 // The number of entries to write. | 251 // The number of entries to write. |
| 232 int entries_to_write_; | 252 int entries_to_write_; |
| 233 | 253 |
| 234 // Number of entries we've written. | 254 // Number of entries we've written. |
| 235 int entries_written_; | 255 int entries_written_; |
| 236 | 256 |
| 237 // Whether we've loaded the last session. | 257 // Whether we've loaded the last session. |
| 238 int load_state_; | 258 int load_state_; |
| 239 | 259 |
| 240 // Results from previously closed tabs/sessions is first added here. When the | 260 // 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 | 261 // results from both us and the session restore service have finished loading |
| 242 // LoadStateChanged is invoked, which adds these entries to entries_. | 262 // LoadStateChanged is invoked, which adds these entries to entries_. |
| 243 ScopedVector<Entry> staging_entries_; | 263 std::vector<std::unique_ptr<Entry>> staging_entries_; |
| 244 | 264 |
| 245 // Used when loading previous tabs/session and open tabs/session. | 265 // Used when loading previous tabs/session and open tabs/session. |
| 246 base::CancelableTaskTracker cancelable_task_tracker_; | 266 base::CancelableTaskTracker cancelable_task_tracker_; |
| 247 | 267 |
| 248 DISALLOW_COPY_AND_ASSIGN(Delegate); | 268 DISALLOW_COPY_AND_ASSIGN(Delegate); |
| 249 }; | 269 }; |
| 250 | 270 |
| 251 PersistentTabRestoreService::Delegate::Delegate(TabRestoreServiceClient* client) | 271 PersistentTabRestoreService::Delegate::Delegate(TabRestoreServiceClient* client) |
| 252 : client_(client), | 272 : client_(client), |
| 253 base_session_service_( | 273 base_session_service_( |
| (...skipping 26 matching lines...) Expand all Loading... |
| 280 base_session_service_->set_pending_reset(true); | 300 base_session_service_->set_pending_reset(true); |
| 281 } | 301 } |
| 282 if (to_write_count) { | 302 if (to_write_count) { |
| 283 // Write the to_write_count most recently added entries out. The most | 303 // 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 | 304 // recently added entry is at the front, so we use a reverse iterator to |
| 285 // write in the order the entries were added. | 305 // write in the order the entries were added. |
| 286 Entries::const_reverse_iterator i = entries.rbegin(); | 306 Entries::const_reverse_iterator i = entries.rbegin(); |
| 287 DCHECK(static_cast<size_t>(to_write_count) <= entries.size()); | 307 DCHECK(static_cast<size_t>(to_write_count) <= entries.size()); |
| 288 std::advance(i, entries.size() - static_cast<int>(to_write_count)); | 308 std::advance(i, entries.size() - static_cast<int>(to_write_count)); |
| 289 for (; i != entries.rend(); ++i) { | 309 for (; i != entries.rend(); ++i) { |
| 290 Entry* entry = *i; | 310 Entry& entry = **i; |
| 291 if (entry->type == TAB) { | 311 switch (entry.type) { |
| 292 Tab* tab = static_cast<Tab*>(entry); | 312 case TAB: { |
| 293 int selected_index = GetSelectedNavigationIndexToPersist(*tab); | 313 Tab& tab = static_cast<Tab&>(entry); |
| 294 if (selected_index != -1) | 314 int selected_index = GetSelectedNavigationIndexToPersist(tab); |
| 295 ScheduleCommandsForTab(*tab, selected_index); | 315 if (selected_index != -1) |
| 296 } else { | 316 ScheduleCommandsForTab(tab, selected_index); |
| 297 ScheduleCommandsForWindow(*static_cast<Window*>(entry)); | 317 break; |
| 318 } |
| 319 case WINDOW: |
| 320 ScheduleCommandsForWindow(static_cast<Window&>(entry)); |
| 321 break; |
| 298 } | 322 } |
| 299 entries_written_++; | 323 entries_written_++; |
| 300 } | 324 } |
| 301 } | 325 } |
| 302 if (base_session_service_->pending_reset()) | 326 if (base_session_service_->pending_reset()) |
| 303 entries_written_ = 0; | 327 entries_written_ = 0; |
| 304 } | 328 } |
| 305 | 329 |
| 306 void PersistentTabRestoreService::Delegate::OnClearEntries() { | 330 void PersistentTabRestoreService::Delegate::OnClearEntries() { |
| 307 // Mark all the tabs as closed so that we don't attempt to restore them. | 331 // 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(); | 397 base_session_service_->DeleteLastSession(); |
| 374 } | 398 } |
| 375 | 399 |
| 376 bool PersistentTabRestoreService::Delegate::IsLoaded() const { | 400 bool PersistentTabRestoreService::Delegate::IsLoaded() const { |
| 377 return !(load_state_ & (NOT_LOADED | LOADING)); | 401 return !(load_state_ & (NOT_LOADED | LOADING)); |
| 378 } | 402 } |
| 379 | 403 |
| 380 // static | 404 // static |
| 381 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( | 405 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( |
| 382 std::vector<SessionWindow*>* windows, | 406 std::vector<SessionWindow*>* windows, |
| 383 std::vector<Entry*>* entries) { | 407 std::vector<std::unique_ptr<Entry>>* entries) { |
| 384 for (size_t i = 0; i < windows->size(); ++i) { | 408 for (size_t i = 0; i < windows->size(); ++i) { |
| 385 std::unique_ptr<Window> window(new Window()); | 409 std::unique_ptr<Window> window(new Window()); |
| 386 if (ConvertSessionWindowToWindow((*windows)[i], window.get())) | 410 if (ConvertSessionWindowToWindow((*windows)[i], window.get())) |
| 387 entries->push_back(window.release()); | 411 entries->push_back(std::move(window)); |
| 388 } | 412 } |
| 389 } | 413 } |
| 390 | 414 |
| 391 void PersistentTabRestoreService::Delegate::Shutdown() { | 415 void PersistentTabRestoreService::Delegate::Shutdown() { |
| 392 base_session_service_->Save(); | 416 base_session_service_->Save(); |
| 393 } | 417 } |
| 394 | 418 |
| 395 void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( | 419 void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( |
| 396 const Window& window) { | 420 const Window& window) { |
| 397 DCHECK(!window.tabs.empty()); | 421 DCHECK(!window.tabs.empty()); |
| 398 int selected_tab = window.selected_tab_index; | 422 int selected_tab = window.selected_tab_index; |
| 399 int valid_tab_count = 0; | 423 int valid_tab_count = 0; |
| 400 int real_selected_tab = selected_tab; | 424 int real_selected_tab = selected_tab; |
| 401 for (size_t i = 0; i < window.tabs.size(); ++i) { | 425 for (size_t i = 0; i < window.tabs.size(); ++i) { |
| 402 if (GetSelectedNavigationIndexToPersist(window.tabs[i]) != -1) { | 426 if (GetSelectedNavigationIndexToPersist(*window.tabs[i]) != -1) { |
| 403 valid_tab_count++; | 427 valid_tab_count++; |
| 404 } else if (static_cast<int>(i) < selected_tab) { | 428 } else if (static_cast<int>(i) < selected_tab) { |
| 405 real_selected_tab--; | 429 real_selected_tab--; |
| 406 } | 430 } |
| 407 } | 431 } |
| 408 if (valid_tab_count == 0) | 432 if (valid_tab_count == 0) |
| 409 return; // No tabs to persist. | 433 return; // No tabs to persist. |
| 410 | 434 |
| 411 base_session_service_->ScheduleCommand(CreateWindowCommand( | 435 base_session_service_->ScheduleCommand(CreateWindowCommand( |
| 412 window.id, std::min(real_selected_tab, valid_tab_count - 1), | 436 window.id, std::min(real_selected_tab, valid_tab_count - 1), |
| 413 valid_tab_count, window.timestamp)); | 437 valid_tab_count, window.timestamp)); |
| 414 | 438 |
| 415 if (!window.app_name.empty()) { | 439 if (!window.app_name.empty()) { |
| 416 base_session_service_->ScheduleCommand(CreateSetWindowAppNameCommand( | 440 base_session_service_->ScheduleCommand(CreateSetWindowAppNameCommand( |
| 417 kCommandSetWindowAppName, window.id, window.app_name)); | 441 kCommandSetWindowAppName, window.id, window.app_name)); |
| 418 } | 442 } |
| 419 | 443 |
| 420 for (size_t i = 0; i < window.tabs.size(); ++i) { | 444 for (size_t i = 0; i < window.tabs.size(); ++i) { |
| 421 int selected_index = GetSelectedNavigationIndexToPersist(window.tabs[i]); | 445 int selected_index = GetSelectedNavigationIndexToPersist(*window.tabs[i]); |
| 422 if (selected_index != -1) | 446 if (selected_index != -1) |
| 423 ScheduleCommandsForTab(window.tabs[i], selected_index); | 447 ScheduleCommandsForTab(*window.tabs[i], selected_index); |
| 424 } | 448 } |
| 425 } | 449 } |
| 426 | 450 |
| 427 void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( | 451 void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( |
| 428 const Tab& tab, | 452 const Tab& tab, |
| 429 int selected_index) { | 453 int selected_index) { |
| 430 const std::vector<SerializedNavigationEntry>& navigations = tab.navigations; | 454 const std::vector<SerializedNavigationEntry>& navigations = tab.navigations; |
| 431 int max_index = static_cast<int>(navigations.size()); | 455 int max_index = static_cast<int>(navigations.size()); |
| 432 | 456 |
| 433 // Determine the first navigation we'll persist. | 457 // Determine the first navigation we'll persist. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 !client_->ShouldTrackURLForRestore( | 572 !client_->ShouldTrackURLForRestore( |
| 549 navigations[selected_index].virtual_url())) { | 573 navigations[selected_index].virtual_url())) { |
| 550 selected_index++; | 574 selected_index++; |
| 551 } | 575 } |
| 552 | 576 |
| 553 return (selected_index == max_index) ? -1 : selected_index; | 577 return (selected_index == max_index) ? -1 : selected_index; |
| 554 } | 578 } |
| 555 | 579 |
| 556 void PersistentTabRestoreService::Delegate::OnGotLastSessionCommands( | 580 void PersistentTabRestoreService::Delegate::OnGotLastSessionCommands( |
| 557 ScopedVector<SessionCommand> commands) { | 581 ScopedVector<SessionCommand> commands) { |
| 558 std::vector<Entry*> entries; | 582 std::vector<std::unique_ptr<TabRestoreService::Entry>> entries; |
| 559 CreateEntriesFromCommands(commands.get(), &entries); | 583 CreateEntriesFromCommands(commands.get(), &entries); |
| 560 // Closed tabs always go to the end. | 584 // Closed tabs always go to the end. |
| 561 staging_entries_.insert(staging_entries_.end(), entries.begin(), | 585 staging_entries_.insert(staging_entries_.end(), |
| 562 entries.end()); | 586 make_move_iterator(entries.begin()), |
| 587 make_move_iterator(entries.end())); |
| 563 load_state_ |= LOADED_LAST_TABS; | 588 load_state_ |= LOADED_LAST_TABS; |
| 564 LoadStateChanged(); | 589 LoadStateChanged(); |
| 565 } | 590 } |
| 566 | 591 |
| 567 void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( | 592 void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( |
| 568 const std::vector<SessionCommand*>& commands, | 593 const std::vector<SessionCommand*>& commands, |
| 569 std::vector<Entry*>* loaded_entries) { | 594 std::vector<std::unique_ptr<Entry>>* loaded_entries) { |
| 570 if (tab_restore_service_helper_->entries().size() == kMaxEntries) | 595 if (tab_restore_service_helper_->entries().size() == kMaxEntries) |
| 571 return; | 596 return; |
| 572 | 597 |
| 573 // Iterate through the commands populating entries and id_to_entry. | 598 // Iterate through the commands, populating |entries|. |
| 574 ScopedVector<Entry> entries; | 599 std::vector<std::unique_ptr<Entry>> entries; |
| 575 IDToEntry id_to_entry; | |
| 576 // If non-null we're processing the navigations of this tab. | 600 // If non-null we're processing the navigations of this tab. |
| 577 Tab* current_tab = NULL; | 601 Tab* current_tab = nullptr; |
| 578 // If non-null we're processing the tabs of this window. | 602 // If non-null we're processing the tabs of this window. |
| 579 Window* current_window = NULL; | 603 Window* current_window = nullptr; |
| 580 // If > 0, we've gotten a window command but not all the tabs yet. | 604 // If > 0, we've gotten a window command but not all the tabs yet. |
| 581 int pending_window_tabs = 0; | 605 int pending_window_tabs = 0; |
| 582 for (std::vector<SessionCommand*>::const_iterator i = commands.begin(); | 606 for (std::vector<SessionCommand*>::const_iterator i = commands.begin(); |
| 583 i != commands.end(); ++i) { | 607 i != commands.end(); ++i) { |
| 584 const SessionCommand& command = *(*i); | 608 const SessionCommand& command = *(*i); |
| 585 switch (command.id()) { | 609 switch (command.id()) { |
| 586 case kCommandRestoredEntry: { | 610 case kCommandRestoredEntry: { |
| 587 if (pending_window_tabs > 0) { | 611 if (pending_window_tabs > 0) { |
| 588 // Should never receive a restored command while waiting for all the | 612 // Should never receive a restored command while waiting for all the |
| 589 // tabs in a window. | 613 // tabs in a window. |
| 590 return; | 614 return; |
| 591 } | 615 } |
| 592 | 616 |
| 593 current_tab = NULL; | 617 current_tab = nullptr; |
| 594 current_window = NULL; | 618 current_window = nullptr; |
| 595 | 619 |
| 596 RestoredEntryPayload payload; | 620 RestoredEntryPayload payload; |
| 597 if (!command.GetPayload(&payload, sizeof(payload))) | 621 if (!command.GetPayload(&payload, sizeof(payload))) |
| 598 return; | 622 return; |
| 599 RemoveEntryByID(payload, &id_to_entry, &(entries.get())); | 623 RemoveEntryByID(payload, &entries); |
| 600 break; | 624 break; |
| 601 } | 625 } |
| 602 | 626 |
| 603 case kCommandWindow: { | 627 case kCommandWindow: { |
| 604 WindowPayload2 payload; | 628 WindowPayload2 payload; |
| 605 if (pending_window_tabs > 0) { | 629 if (pending_window_tabs > 0) { |
| 606 // Should never receive a window command while waiting for all the | 630 // Should never receive a window command while waiting for all the |
| 607 // tabs in a window. | 631 // tabs in a window. |
| 608 return; | 632 return; |
| 609 } | 633 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 623 // unknown timestamp. | 647 // unknown timestamp. |
| 624 payload.timestamp = 0; | 648 payload.timestamp = 0; |
| 625 } | 649 } |
| 626 | 650 |
| 627 pending_window_tabs = payload.num_tabs; | 651 pending_window_tabs = payload.num_tabs; |
| 628 if (pending_window_tabs <= 0) { | 652 if (pending_window_tabs <= 0) { |
| 629 // Should always have at least 1 tab. Likely indicates corruption. | 653 // Should always have at least 1 tab. Likely indicates corruption. |
| 630 return; | 654 return; |
| 631 } | 655 } |
| 632 | 656 |
| 633 RemoveEntryByID(payload.window_id, &id_to_entry, &(entries.get())); | 657 RemoveEntryByID(payload.window_id, &entries); |
| 634 | 658 |
| 635 current_window = new Window(); | 659 entries.push_back(base::MakeUnique<Window>()); |
| 660 current_window = static_cast<Window*>(entries.back().get()); |
| 636 current_window->selected_tab_index = payload.selected_tab_index; | 661 current_window->selected_tab_index = payload.selected_tab_index; |
| 637 current_window->timestamp = | 662 current_window->timestamp = |
| 638 base::Time::FromInternalValue(payload.timestamp); | 663 base::Time::FromInternalValue(payload.timestamp); |
| 639 entries.push_back(current_window); | |
| 640 id_to_entry[payload.window_id] = current_window; | |
| 641 break; | 664 break; |
| 642 } | 665 } |
| 643 | 666 |
| 644 case kCommandSelectedNavigationInTab: { | 667 case kCommandSelectedNavigationInTab: { |
| 645 SelectedNavigationInTabPayload2 payload; | 668 SelectedNavigationInTabPayload2 payload; |
| 646 if (!command.GetPayload(&payload, sizeof(payload))) { | 669 if (!command.GetPayload(&payload, sizeof(payload))) { |
| 647 SelectedNavigationInTabPayload old_payload; | 670 SelectedNavigationInTabPayload old_payload; |
| 648 if (!command.GetPayload(&old_payload, sizeof(old_payload))) | 671 if (!command.GetPayload(&old_payload, sizeof(old_payload))) |
| 649 return; | 672 return; |
| 650 payload.id = old_payload.id; | 673 payload.id = old_payload.id; |
| 651 payload.index = old_payload.index; | 674 payload.index = old_payload.index; |
| 652 // Since we don't have a time use time 0 which is used to mark as an | 675 // Since we don't have a time use time 0 which is used to mark as an |
| 653 // unknown timestamp. | 676 // unknown timestamp. |
| 654 payload.timestamp = 0; | 677 payload.timestamp = 0; |
| 655 } | 678 } |
| 656 | 679 |
| 657 if (pending_window_tabs > 0) { | 680 if (pending_window_tabs > 0) { |
| 658 if (!current_window) { | 681 if (!current_window) { |
| 659 // We should have created a window already. | 682 // We should have created a window already. |
| 660 NOTREACHED(); | 683 NOTREACHED(); |
| 661 return; | 684 return; |
| 662 } | 685 } |
| 663 current_window->tabs.resize(current_window->tabs.size() + 1); | 686 current_window->tabs.push_back(base::MakeUnique<Tab>()); |
| 664 current_tab = &(current_window->tabs.back()); | 687 current_tab = current_window->tabs.back().get(); |
| 665 if (--pending_window_tabs == 0) | 688 if (--pending_window_tabs == 0) |
| 666 current_window = NULL; | 689 current_window = nullptr; |
| 667 } else { | 690 } else { |
| 668 RemoveEntryByID(payload.id, &id_to_entry, &(entries.get())); | 691 RemoveEntryByID(payload.id, &entries); |
| 669 current_tab = new Tab(); | 692 entries.push_back(base::MakeUnique<Tab>()); |
| 670 id_to_entry[payload.id] = current_tab; | 693 current_tab = static_cast<Tab*>(entries.back().get()); |
| 671 current_tab->timestamp = | 694 current_tab->timestamp = |
| 672 base::Time::FromInternalValue(payload.timestamp); | 695 base::Time::FromInternalValue(payload.timestamp); |
| 673 entries.push_back(current_tab); | |
| 674 } | 696 } |
| 675 current_tab->current_navigation_index = payload.index; | 697 current_tab->current_navigation_index = payload.index; |
| 676 break; | 698 break; |
| 677 } | 699 } |
| 678 | 700 |
| 679 case kCommandUpdateTabNavigation: { | 701 case kCommandUpdateTabNavigation: { |
| 680 if (!current_tab) { | 702 if (!current_tab) { |
| 681 // Should be in a tab when we get this. | 703 // Should be in a tab when we get this. |
| 682 return; | 704 return; |
| 683 } | 705 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 break; | 772 break; |
| 751 } | 773 } |
| 752 | 774 |
| 753 default: | 775 default: |
| 754 // Unknown type, usually indicates corruption of file. Ignore it. | 776 // Unknown type, usually indicates corruption of file. Ignore it. |
| 755 return; | 777 return; |
| 756 } | 778 } |
| 757 } | 779 } |
| 758 | 780 |
| 759 // If there was corruption some of the entries won't be valid. | 781 // If there was corruption some of the entries won't be valid. |
| 760 ValidateAndDeleteEmptyEntries(&(entries.get())); | 782 ValidateAndDeleteEmptyEntries(&entries); |
| 761 | 783 |
| 762 loaded_entries->swap(entries.get()); | 784 loaded_entries->swap(entries); |
| 763 } | 785 } |
| 764 | 786 |
| 765 // static | 787 // static |
| 766 void PersistentTabRestoreService::Delegate::ValidateAndDeleteEmptyEntries( | 788 void PersistentTabRestoreService::Delegate::ValidateAndDeleteEmptyEntries( |
| 767 std::vector<Entry*>* entries) { | 789 std::vector<std::unique_ptr<Entry>>* entries) { |
| 768 std::vector<Entry*> valid_entries; | 790 std::vector<std::unique_ptr<Entry>> valid_entries; |
| 769 std::vector<Entry*> invalid_entries; | |
| 770 | 791 |
| 771 // Iterate from the back so that we keep the most recently closed entries. | 792 // Iterate from the back so that we keep the most recently closed entries. |
| 772 for (std::vector<Entry*>::reverse_iterator i = entries->rbegin(); | 793 for (auto i = entries->rbegin(); i != entries->rend(); ++i) { |
| 773 i != entries->rend(); ++i) { | 794 if (TabRestoreServiceHelper::ValidateEntry(**i)) |
| 774 if (TabRestoreServiceHelper::ValidateEntry(*i)) | 795 valid_entries.push_back(std::move(*i)); |
| 775 valid_entries.push_back(*i); | |
| 776 else | |
| 777 invalid_entries.push_back(*i); | |
| 778 } | 796 } |
| 779 // NOTE: at this point the entries are ordered with newest at the front. | 797 // NOTE: at this point the entries are ordered with newest at the front. |
| 780 entries->swap(valid_entries); | 798 entries->swap(valid_entries); |
| 781 | |
| 782 // Delete the remaining entries. | |
| 783 STLDeleteElements(&invalid_entries); | |
| 784 } | 799 } |
| 785 | 800 |
| 786 void PersistentTabRestoreService::Delegate::OnGotPreviousSession( | 801 void PersistentTabRestoreService::Delegate::OnGotPreviousSession( |
| 787 ScopedVector<SessionWindow> windows, | 802 ScopedVector<SessionWindow> windows, |
| 788 SessionID::id_type ignored_active_window) { | 803 SessionID::id_type ignored_active_window) { |
| 789 std::vector<Entry*> entries; | 804 std::vector<std::unique_ptr<Entry>> entries; |
| 790 CreateEntriesFromWindows(&windows.get(), &entries); | 805 CreateEntriesFromWindows(&windows.get(), &entries); |
| 791 // Previous session tabs go first. | 806 // Previous session tabs go first. |
| 792 staging_entries_.insert(staging_entries_.begin(), entries.begin(), | 807 staging_entries_.insert(staging_entries_.begin(), |
| 793 entries.end()); | 808 make_move_iterator(entries.begin()), |
| 809 make_move_iterator(entries.end())); |
| 794 load_state_ |= LOADED_LAST_SESSION; | 810 load_state_ |= LOADED_LAST_SESSION; |
| 795 LoadStateChanged(); | 811 LoadStateChanged(); |
| 796 } | 812 } |
| 797 | 813 |
| 798 bool PersistentTabRestoreService::Delegate::ConvertSessionWindowToWindow( | 814 bool PersistentTabRestoreService::Delegate::ConvertSessionWindowToWindow( |
| 799 SessionWindow* session_window, | 815 SessionWindow* session_window, |
| 800 Window* window) { | 816 Window* window) { |
| 801 for (size_t i = 0; i < session_window->tabs.size(); ++i) { | 817 for (size_t i = 0; i < session_window->tabs.size(); ++i) { |
| 802 if (!session_window->tabs[i]->navigations.empty()) { | 818 if (!session_window->tabs[i]->navigations.empty()) { |
| 803 window->tabs.resize(window->tabs.size() + 1); | 819 window->tabs.push_back(base::MakeUnique<Tab>()); |
| 804 Tab& tab = window->tabs.back(); | 820 Tab& tab = *window->tabs.back(); |
| 805 tab.pinned = session_window->tabs[i]->pinned; | 821 tab.pinned = session_window->tabs[i]->pinned; |
| 806 tab.navigations.swap(session_window->tabs[i]->navigations); | 822 tab.navigations.swap(session_window->tabs[i]->navigations); |
| 807 tab.current_navigation_index = | 823 tab.current_navigation_index = |
| 808 session_window->tabs[i]->current_navigation_index; | 824 session_window->tabs[i]->current_navigation_index; |
| 809 tab.extension_app_id = session_window->tabs[i]->extension_app_id; | 825 tab.extension_app_id = session_window->tabs[i]->extension_app_id; |
| 810 tab.timestamp = base::Time(); | 826 tab.timestamp = base::Time(); |
| 811 } | 827 } |
| 812 } | 828 } |
| 813 if (window->tabs.empty()) | 829 if (window->tabs.empty()) |
| 814 return false; | 830 return false; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 843 // kMaxEntries. | 859 // kMaxEntries. |
| 844 int surplus = kMaxEntries - entries.size(); | 860 int surplus = kMaxEntries - entries.size(); |
| 845 CHECK_LE(0, surplus); | 861 CHECK_LE(0, surplus); |
| 846 CHECK_GE(static_cast<int>(staging_entries_.size()), surplus); | 862 CHECK_GE(static_cast<int>(staging_entries_.size()), surplus); |
| 847 staging_entries_.erase( | 863 staging_entries_.erase( |
| 848 staging_entries_.begin() + (kMaxEntries - entries.size()), | 864 staging_entries_.begin() + (kMaxEntries - entries.size()), |
| 849 staging_entries_.end()); | 865 staging_entries_.end()); |
| 850 } | 866 } |
| 851 | 867 |
| 852 // And add them. | 868 // And add them. |
| 853 for (size_t i = 0; i < staging_entries_.size(); ++i) { | 869 for (auto& staging_entry : staging_entries_) { |
| 854 staging_entries_[i]->from_last_session = true; | 870 staging_entry->from_last_session = true; |
| 855 tab_restore_service_helper_->AddEntry(staging_entries_[i], false, false); | 871 tab_restore_service_helper_->AddEntry(std::move(staging_entry), false, |
| 872 false); |
| 856 } | 873 } |
| 857 | 874 |
| 858 // AddEntry takes ownership of the entry, need to clear out entries so that | 875 staging_entries_.clear(); |
| 859 // it doesn't delete them. | 876 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 | 877 |
| 867 tab_restore_service_helper_->PruneEntries(); | 878 tab_restore_service_helper_->PruneEntries(); |
| 868 tab_restore_service_helper_->NotifyTabsChanged(); | 879 tab_restore_service_helper_->NotifyTabsChanged(); |
| 869 | 880 |
| 870 tab_restore_service_helper_->NotifyLoaded(); | 881 tab_restore_service_helper_->NotifyLoaded(); |
| 871 } | 882 } |
| 872 | 883 |
| 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 ------------------------------------------------- | 884 // PersistentTabRestoreService ------------------------------------------------- |
| 908 | 885 |
| 909 PersistentTabRestoreService::PersistentTabRestoreService( | 886 PersistentTabRestoreService::PersistentTabRestoreService( |
| 910 std::unique_ptr<TabRestoreServiceClient> client, | 887 std::unique_ptr<TabRestoreServiceClient> client, |
| 911 TimeFactory* time_factory) | 888 TimeFactory* time_factory) |
| 912 : client_(std::move(client)), | 889 : client_(std::move(client)), |
| 913 delegate_(new Delegate(client_.get())), | 890 delegate_(new Delegate(client_.get())), |
| 914 helper_(this, delegate_.get(), client_.get(), time_factory) { | 891 helper_(this, delegate_.get(), client_.get(), time_factory) { |
| 915 delegate_->set_tab_restore_service_helper(&helper_); | 892 delegate_->set_tab_restore_service_helper(&helper_); |
| 916 } | 893 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 946 | 923 |
| 947 const TabRestoreService::Entries& PersistentTabRestoreService::entries() const { | 924 const TabRestoreService::Entries& PersistentTabRestoreService::entries() const { |
| 948 return helper_.entries(); | 925 return helper_.entries(); |
| 949 } | 926 } |
| 950 | 927 |
| 951 std::vector<LiveTab*> PersistentTabRestoreService::RestoreMostRecentEntry( | 928 std::vector<LiveTab*> PersistentTabRestoreService::RestoreMostRecentEntry( |
| 952 LiveTabContext* context) { | 929 LiveTabContext* context) { |
| 953 return helper_.RestoreMostRecentEntry(context); | 930 return helper_.RestoreMostRecentEntry(context); |
| 954 } | 931 } |
| 955 | 932 |
| 956 TabRestoreService::Tab* PersistentTabRestoreService::RemoveTabEntryById( | 933 std::unique_ptr<TabRestoreService::Tab> |
| 957 SessionID::id_type id) { | 934 PersistentTabRestoreService::RemoveTabEntryById(SessionID::id_type id) { |
| 958 return helper_.RemoveTabEntryById(id); | 935 return helper_.RemoveTabEntryById(id); |
| 959 } | 936 } |
| 960 | 937 |
| 961 std::vector<LiveTab*> PersistentTabRestoreService::RestoreEntryById( | 938 std::vector<LiveTab*> PersistentTabRestoreService::RestoreEntryById( |
| 962 LiveTabContext* context, | 939 LiveTabContext* context, |
| 963 SessionID::id_type id, | 940 SessionID::id_type id, |
| 964 WindowOpenDisposition disposition) { | 941 WindowOpenDisposition disposition) { |
| 965 return helper_.RestoreEntryById(context, id, disposition); | 942 return helper_.RestoreEntryById(context, id, disposition); |
| 966 } | 943 } |
| 967 | 944 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 983 | 960 |
| 984 TabRestoreService::Entries* PersistentTabRestoreService::mutable_entries() { | 961 TabRestoreService::Entries* PersistentTabRestoreService::mutable_entries() { |
| 985 return &helper_.entries_; | 962 return &helper_.entries_; |
| 986 } | 963 } |
| 987 | 964 |
| 988 void PersistentTabRestoreService::PruneEntries() { | 965 void PersistentTabRestoreService::PruneEntries() { |
| 989 helper_.PruneEntries(); | 966 helper_.PruneEntries(); |
| 990 } | 967 } |
| 991 | 968 |
| 992 } // namespace sessions | 969 } // namespace sessions |
| OLD | NEW |