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 |