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> |
(...skipping 27 matching lines...) Expand all Loading... |
38 // 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 |
39 // 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. |
40 struct SelectedNavigationInTabPayload { | 40 struct SelectedNavigationInTabPayload { |
41 SessionID::id_type id; | 41 SessionID::id_type id; |
42 int32_t index; | 42 int32_t index; |
43 }; | 43 }; |
44 | 44 |
45 // 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 |
46 // 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 |
47 // struct must be POD, because we memset the contents. | 47 // struct must be POD, because we memset the contents. |
48 struct WindowPayload { | 48 struct WindowPayloadObsolete { |
49 SessionID::id_type window_id; | 49 SessionID::id_type window_id; |
50 int32_t selected_tab_index; | 50 int32_t selected_tab_index; |
51 int32_t num_tabs; | 51 int32_t num_tabs; |
52 }; | 52 }; |
53 | 53 |
54 // Payload used for the start of a window close. This struct must be POD, | 54 // Payload used for the start of a window close. This struct must be POD, |
55 // because we memset the contents. | 55 // because we memset the contents. This is an older version of the struct that |
56 struct WindowPayload2 : WindowPayload { | 56 // is used for backwards compat when it comes to reading the session files. |
| 57 struct WindowPayloadObsolete2 : WindowPayloadObsolete { |
57 int64_t timestamp; | 58 int64_t timestamp; |
58 }; | 59 }; |
59 | 60 |
60 // Payload used for the start of a tab close. | 61 // Payload used for the start of a tab close. |
61 struct SelectedNavigationInTabPayload2 : SelectedNavigationInTabPayload { | 62 struct SelectedNavigationInTabPayload2 : SelectedNavigationInTabPayload { |
62 int64_t timestamp; | 63 int64_t timestamp; |
63 }; | 64 }; |
64 | 65 |
65 // Used to indicate what has loaded. | 66 // Used to indicate what has loaded. |
66 enum LoadState { | 67 enum LoadState { |
(...skipping 22 matching lines...) Expand all Loading... |
89 // the user agent override if it was using one. This is | 90 // the user agent override if it was using one. This is |
90 // followed by any number of kCommandUpdateTabNavigation commands (1 per | 91 // followed by any number of kCommandUpdateTabNavigation commands (1 per |
91 // navigation entry). | 92 // navigation entry). |
92 // . When the user closes a window a kCommandSelectedNavigationInTab command | 93 // . When the user closes a window a kCommandSelectedNavigationInTab command |
93 // is written out and followed by n tab closed sequences (as previoulsy | 94 // is written out and followed by n tab closed sequences (as previoulsy |
94 // described). | 95 // described). |
95 // . When the user restores an entry a command of type kCommandRestoredEntry | 96 // . When the user restores an entry a command of type kCommandRestoredEntry |
96 // is written. | 97 // is written. |
97 const SessionCommand::id_type kCommandUpdateTabNavigation = 1; | 98 const SessionCommand::id_type kCommandUpdateTabNavigation = 1; |
98 const SessionCommand::id_type kCommandRestoredEntry = 2; | 99 const SessionCommand::id_type kCommandRestoredEntry = 2; |
99 const SessionCommand::id_type kCommandWindow = 3; | 100 const SessionCommand::id_type kCommandWindowDeprecated = 3; |
100 const SessionCommand::id_type kCommandSelectedNavigationInTab = 4; | 101 const SessionCommand::id_type kCommandSelectedNavigationInTab = 4; |
101 const SessionCommand::id_type kCommandPinnedState = 5; | 102 const SessionCommand::id_type kCommandPinnedState = 5; |
102 const SessionCommand::id_type kCommandSetExtensionAppID = 6; | 103 const SessionCommand::id_type kCommandSetExtensionAppID = 6; |
103 const SessionCommand::id_type kCommandSetWindowAppName = 7; | 104 const SessionCommand::id_type kCommandSetWindowAppName = 7; |
104 const SessionCommand::id_type kCommandSetTabUserAgentOverride = 8; | 105 const SessionCommand::id_type kCommandSetTabUserAgentOverride = 8; |
| 106 const SessionCommand::id_type kCommandWindow = 9; |
105 | 107 |
106 // Number of entries (not commands) before we clobber the file and write | 108 // Number of entries (not commands) before we clobber the file and write |
107 // everything. | 109 // everything. |
108 const int kEntriesPerReset = 40; | 110 const int kEntriesPerReset = 40; |
109 | 111 |
110 const size_t kMaxEntries = TabRestoreServiceHelper::kMaxEntries; | 112 const size_t kMaxEntries = TabRestoreServiceHelper::kMaxEntries; |
111 | 113 |
112 void RemoveEntryByID( | 114 void RemoveEntryByID( |
113 SessionID::id_type id, | 115 SessionID::id_type id, |
114 std::vector<std::unique_ptr<TabRestoreService::Entry>>* entries) { | 116 std::vector<std::unique_ptr<TabRestoreService::Entry>>* entries) { |
(...skipping 13 matching lines...) Expand all Loading... |
128 // Erase it if it's our target. | 130 // Erase it if it's our target. |
129 if (tab.id == id) { | 131 if (tab.id == id) { |
130 window.tabs.erase(it); | 132 window.tabs.erase(it); |
131 return; | 133 return; |
132 } | 134 } |
133 } | 135 } |
134 } | 136 } |
135 } | 137 } |
136 } | 138 } |
137 | 139 |
| 140 // An enum that corresponds to ui::WindowShowStates. This needs to be kept in |
| 141 // sync with that enum. Moreover, the integer values corresponding to each show |
| 142 // state need to be stable in this enum (which is not necessarily true about the |
| 143 // ui::WindowShowStates enum). |
| 144 enum SerializedWindowShowState : int { |
| 145 kSerializedShowStateInvalid = -1, |
| 146 kSerializedShowStateDefault = 0, |
| 147 kSerializedShowStateNormal = 1, |
| 148 kSerializedShowStateMinimized = 2, |
| 149 kSerializedShowStateMaximized = 3, |
| 150 kSerializedShowStateInactive = 4, |
| 151 kSerializedShowStateFullscreen = 5, |
| 152 }; |
| 153 |
| 154 // Converts a window show state to an integer. This function needs to be kept |
| 155 // up to date with the SerializedWindowShowState enum. |
| 156 int SerializeWindowShowState(ui::WindowShowState show_state) { |
| 157 switch (show_state) { |
| 158 case ui::SHOW_STATE_DEFAULT: |
| 159 return kSerializedShowStateDefault; |
| 160 case ui::SHOW_STATE_NORMAL: |
| 161 return kSerializedShowStateNormal; |
| 162 case ui::SHOW_STATE_MINIMIZED: |
| 163 return kSerializedShowStateMinimized; |
| 164 case ui::SHOW_STATE_MAXIMIZED: |
| 165 return kSerializedShowStateMaximized; |
| 166 case ui::SHOW_STATE_INACTIVE: |
| 167 return kSerializedShowStateInactive; |
| 168 case ui::SHOW_STATE_FULLSCREEN: |
| 169 return kSerializedShowStateFullscreen; |
| 170 case ui::SHOW_STATE_END: |
| 171 // This should never happen. |
| 172 NOTREACHED(); |
| 173 } |
| 174 return kSerializedShowStateInvalid; |
| 175 } |
| 176 |
| 177 // Converts an integer to a window show state. Returns true on success, false |
| 178 // otherwise. This function needs to be kept up to date with the |
| 179 // SerializedWindowShowState enum. |
| 180 bool DeserializeWindowShowState(int show_state_int, |
| 181 ui::WindowShowState* show_state) { |
| 182 switch (static_cast<SerializedWindowShowState>(show_state_int)) { |
| 183 case kSerializedShowStateDefault: |
| 184 *show_state = ui::SHOW_STATE_DEFAULT; |
| 185 return true; |
| 186 case kSerializedShowStateNormal: |
| 187 *show_state = ui::SHOW_STATE_NORMAL; |
| 188 return true; |
| 189 case kSerializedShowStateMinimized: |
| 190 *show_state = ui::SHOW_STATE_MINIMIZED; |
| 191 return true; |
| 192 case kSerializedShowStateMaximized: |
| 193 *show_state = ui::SHOW_STATE_MAXIMIZED; |
| 194 return true; |
| 195 case kSerializedShowStateInactive: |
| 196 *show_state = ui::SHOW_STATE_INACTIVE; |
| 197 return true; |
| 198 case kSerializedShowStateFullscreen: |
| 199 *show_state = ui::SHOW_STATE_FULLSCREEN; |
| 200 return true; |
| 201 case kSerializedShowStateInvalid: |
| 202 default: |
| 203 // Ignore unknown values. This could happen if the data is corrupt. |
| 204 break; |
| 205 } |
| 206 return false; |
| 207 } |
| 208 |
| 209 // Superset of WindowPayloadObsolete/WindowPayloadObsolete2 and the other fields |
| 210 // that can appear in the Pickle version of a Window command. This is used as a |
| 211 // convenient destination for parsing the various fields in a WindowCommand. |
| 212 struct WindowCommandFields { |
| 213 // Fields in WindowPayloadObsolete/WindowPayloadObsolete2/Pickle: |
| 214 int window_id = 0; |
| 215 int selected_tab_index = 0; |
| 216 int num_tabs = 0; |
| 217 |
| 218 // Fields in WindowPayloadObsolete2/Pickle: |
| 219 int64_t timestamp = 0; |
| 220 |
| 221 // Fields in Pickle: |
| 222 // Completely zeroed position/dimensions indicates that defaults should be |
| 223 // used. |
| 224 int window_x = 0; |
| 225 int window_y = 0; |
| 226 int window_width = 0; |
| 227 int window_height = 0; |
| 228 int window_show_state = 0; |
| 229 std::string workspace; |
| 230 }; |
| 231 |
| 232 std::unique_ptr<sessions::TabRestoreService::Window> |
| 233 CreateWindowEntryFromCommand(const SessionCommand* command, |
| 234 SessionID::id_type* window_id, |
| 235 int32_t* num_tabs) { |
| 236 WindowCommandFields fields; |
| 237 ui::WindowShowState show_state = ui::SHOW_STATE_DEFAULT; |
| 238 |
| 239 if (command->id() == kCommandWindow) { |
| 240 std::unique_ptr<base::Pickle> pickle(command->PayloadAsPickle()); |
| 241 if (!pickle.get()) |
| 242 return nullptr; |
| 243 |
| 244 base::PickleIterator it(*pickle); |
| 245 WindowCommandFields parsed_fields; |
| 246 |
| 247 // The first version of the pickle contains all of the following fields, so |
| 248 // they should all successfully parse if the command is in fact a pickle. |
| 249 if (!it.ReadInt(&parsed_fields.window_id) || |
| 250 !it.ReadInt(&parsed_fields.selected_tab_index) || |
| 251 !it.ReadInt(&parsed_fields.num_tabs) || |
| 252 !it.ReadInt64(&parsed_fields.timestamp) || |
| 253 !it.ReadInt(&parsed_fields.window_x) || |
| 254 !it.ReadInt(&parsed_fields.window_y) || |
| 255 !it.ReadInt(&parsed_fields.window_width) || |
| 256 !it.ReadInt(&parsed_fields.window_height) || |
| 257 !it.ReadInt(&parsed_fields.window_show_state) || |
| 258 !it.ReadString(&parsed_fields.workspace)) { |
| 259 return nullptr; |
| 260 } |
| 261 |
| 262 // Validate the parameters. If the entire pickles parses but any of the |
| 263 // validation fails assume corruption. |
| 264 if (parsed_fields.window_width < 0 || parsed_fields.window_height < 0) |
| 265 return nullptr; |
| 266 |
| 267 // Deserialize the show state, validating it at the same time. |
| 268 if (!DeserializeWindowShowState(parsed_fields.window_show_state, |
| 269 &show_state)) { |
| 270 return nullptr; |
| 271 } |
| 272 |
| 273 // New fields added to the pickle in later versions would be parsed and |
| 274 // validated here. |
| 275 |
| 276 // Copy the parsed data. |
| 277 fields = parsed_fields; |
| 278 } else if (command->id() == kCommandWindowDeprecated) { |
| 279 // Old window commands can be in either of 2 formats. Try the newest first. |
| 280 // These have distinct sizes so are easily distinguished. |
| 281 bool parsed = false; |
| 282 |
| 283 // Try to parse the command as a WindowPayloadObsolete2. |
| 284 WindowPayloadObsolete2 payload2; |
| 285 if (command->GetPayload(&payload2, sizeof(payload2))) { |
| 286 fields.window_id = payload2.window_id; |
| 287 fields.selected_tab_index = payload2.selected_tab_index; |
| 288 fields.num_tabs = payload2.num_tabs; |
| 289 fields.timestamp = payload2.timestamp; |
| 290 parsed = true; |
| 291 } |
| 292 |
| 293 // Finally, try the oldest WindowPayloadObsolete type. |
| 294 if (!parsed) { |
| 295 WindowPayloadObsolete payload; |
| 296 if (command->GetPayload(&payload, sizeof(payload))) { |
| 297 fields.window_id = payload.window_id; |
| 298 fields.selected_tab_index = payload.selected_tab_index; |
| 299 fields.num_tabs = payload.num_tabs; |
| 300 parsed = true; |
| 301 } |
| 302 } |
| 303 |
| 304 // Fail if the old command wasn't able to be parsed in either of the |
| 305 // deprecated formats. |
| 306 if (!parsed) |
| 307 return nullptr; |
| 308 } else { |
| 309 // This should never be called with anything other than a known window |
| 310 // command ID. |
| 311 NOTREACHED(); |
| 312 } |
| 313 |
| 314 // Create the Window entry. |
| 315 std::unique_ptr<sessions::TabRestoreService::Window> window = |
| 316 base::MakeUnique<sessions::TabRestoreService::Window>(); |
| 317 window->selected_tab_index = fields.selected_tab_index; |
| 318 window->timestamp = base::Time::FromInternalValue(fields.timestamp); |
| 319 *window_id = static_cast<SessionID::id_type>(fields.window_id); |
| 320 *num_tabs = fields.num_tabs; |
| 321 |
| 322 // Set the bounds, show state and workspace if valid ones have been provided. |
| 323 if (!(fields.window_x == 0 && fields.window_y == 0 && |
| 324 fields.window_width == 0 && fields.window_height == 0)) { |
| 325 window->bounds.SetRect(fields.window_x, fields.window_y, |
| 326 fields.window_width, fields.window_height); |
| 327 // |show_state| was converted from window->show_state earlier during |
| 328 // validation. |
| 329 window->show_state = show_state; |
| 330 window->workspace = std::move(fields.workspace); |
| 331 } |
| 332 |
| 333 return window; |
| 334 } |
| 335 |
138 } // namespace | 336 } // namespace |
139 | 337 |
140 // PersistentTabRestoreService::Delegate --------------------------------------- | 338 // PersistentTabRestoreService::Delegate --------------------------------------- |
141 | 339 |
142 // This restore service will create and own a BaseSessionService and implement | 340 // This restore service will create and own a BaseSessionService and implement |
143 // the required BaseSessionServiceDelegate. | 341 // the required BaseSessionServiceDelegate. |
144 class PersistentTabRestoreService::Delegate | 342 class PersistentTabRestoreService::Delegate |
145 : public BaseSessionServiceDelegate, | 343 : public BaseSessionServiceDelegate, |
146 public TabRestoreServiceHelper::Observer { | 344 public TabRestoreServiceHelper::Observer { |
147 public: | 345 public: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 | 377 |
180 // Schedules the commands for a window close. | 378 // Schedules the commands for a window close. |
181 void ScheduleCommandsForWindow(const Window& window); | 379 void ScheduleCommandsForWindow(const Window& window); |
182 | 380 |
183 // Schedules the commands for a tab close. |selected_index| gives the index of | 381 // Schedules the commands for a tab close. |selected_index| gives the index of |
184 // the selected navigation. | 382 // the selected navigation. |
185 void ScheduleCommandsForTab(const Tab& tab, int selected_index); | 383 void ScheduleCommandsForTab(const Tab& tab, int selected_index); |
186 | 384 |
187 // Creates a window close command. | 385 // Creates a window close command. |
188 static std::unique_ptr<SessionCommand> CreateWindowCommand( | 386 static std::unique_ptr<SessionCommand> CreateWindowCommand( |
189 SessionID::id_type id, | 387 SessionID::id_type window_id, |
190 int selected_tab_index, | 388 int selected_tab_index, |
191 int num_tabs, | 389 int num_tabs, |
| 390 const gfx::Rect& bounds, |
| 391 ui::WindowShowState show_state, |
| 392 const std::string& workspace, |
192 base::Time timestamp); | 393 base::Time timestamp); |
193 | 394 |
194 // Creates a tab close command. | 395 // Creates a tab close command. |
195 static std::unique_ptr<SessionCommand> CreateSelectedNavigationInTabCommand( | 396 static std::unique_ptr<SessionCommand> CreateSelectedNavigationInTabCommand( |
196 SessionID::id_type tab_id, | 397 SessionID::id_type tab_id, |
197 int32_t index, | 398 int32_t index, |
198 base::Time timestamp); | 399 base::Time timestamp); |
199 | 400 |
200 // Creates a restore command. | 401 // Creates a restore command. |
201 static std::unique_ptr<SessionCommand> CreateRestoredEntryCommand( | 402 static std::unique_ptr<SessionCommand> CreateRestoredEntryCommand( |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 valid_tab_count++; | 623 valid_tab_count++; |
423 } else if (static_cast<int>(i) < selected_tab) { | 624 } else if (static_cast<int>(i) < selected_tab) { |
424 real_selected_tab--; | 625 real_selected_tab--; |
425 } | 626 } |
426 } | 627 } |
427 if (valid_tab_count == 0) | 628 if (valid_tab_count == 0) |
428 return; // No tabs to persist. | 629 return; // No tabs to persist. |
429 | 630 |
430 base_session_service_->ScheduleCommand(CreateWindowCommand( | 631 base_session_service_->ScheduleCommand(CreateWindowCommand( |
431 window.id, std::min(real_selected_tab, valid_tab_count - 1), | 632 window.id, std::min(real_selected_tab, valid_tab_count - 1), |
432 valid_tab_count, window.timestamp)); | 633 valid_tab_count, window.bounds, window.show_state, window.workspace, |
| 634 window.timestamp)); |
433 | 635 |
434 if (!window.app_name.empty()) { | 636 if (!window.app_name.empty()) { |
435 base_session_service_->ScheduleCommand(CreateSetWindowAppNameCommand( | 637 base_session_service_->ScheduleCommand(CreateSetWindowAppNameCommand( |
436 kCommandSetWindowAppName, window.id, window.app_name)); | 638 kCommandSetWindowAppName, window.id, window.app_name)); |
437 } | 639 } |
438 | 640 |
439 for (size_t i = 0; i < window.tabs.size(); ++i) { | 641 for (size_t i = 0; i < window.tabs.size(); ++i) { |
440 int selected_index = GetSelectedNavigationIndexToPersist(*window.tabs[i]); | 642 int selected_index = GetSelectedNavigationIndexToPersist(*window.tabs[i]); |
441 if (selected_index != -1) | 643 if (selected_index != -1) |
442 ScheduleCommandsForTab(*window.tabs[i], selected_index); | 644 ScheduleCommandsForTab(*window.tabs[i], selected_index); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, | 693 CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, |
492 tab.id, | 694 tab.id, |
493 navigations[i])); | 695 navigations[i])); |
494 } | 696 } |
495 } | 697 } |
496 } | 698 } |
497 | 699 |
498 // static | 700 // static |
499 std::unique_ptr<SessionCommand> | 701 std::unique_ptr<SessionCommand> |
500 PersistentTabRestoreService::Delegate::CreateWindowCommand( | 702 PersistentTabRestoreService::Delegate::CreateWindowCommand( |
501 SessionID::id_type id, | 703 SessionID::id_type window_id, |
502 int selected_tab_index, | 704 int selected_tab_index, |
503 int num_tabs, | 705 int num_tabs, |
| 706 const gfx::Rect& bounds, |
| 707 ui::WindowShowState show_state, |
| 708 const std::string& workspace, |
504 base::Time timestamp) { | 709 base::Time timestamp) { |
505 WindowPayload2 payload; | 710 static_assert(sizeof(SessionID::id_type) == sizeof(int), |
506 // |timestamp| is aligned on a 16 byte boundary, leaving 4 bytes of | 711 "SessionID::id_type has changed size."); |
507 // uninitialized memory in the struct. | 712 |
508 memset(&payload, 0, sizeof(payload)); | 713 // Use a pickle to handle marshaling as this command contains variable-length |
509 payload.window_id = id; | 714 // content. |
510 payload.selected_tab_index = selected_tab_index; | 715 base::Pickle pickle; |
511 payload.num_tabs = num_tabs; | 716 pickle.WriteInt(static_cast<int>(window_id)); |
512 payload.timestamp = timestamp.ToInternalValue(); | 717 pickle.WriteInt(selected_tab_index); |
| 718 pickle.WriteInt(num_tabs); |
| 719 pickle.WriteInt64(timestamp.ToInternalValue()); |
| 720 pickle.WriteInt(bounds.x()); |
| 721 pickle.WriteInt(bounds.y()); |
| 722 pickle.WriteInt(bounds.width()); |
| 723 pickle.WriteInt(bounds.height()); |
| 724 pickle.WriteInt(SerializeWindowShowState(show_state)); |
| 725 |
| 726 // Enforce a maximum length on workspace names. A common size is 32 bytes for |
| 727 // GUIDs. |
| 728 if (workspace.size() <= 128) |
| 729 pickle.WriteString(workspace); |
| 730 else |
| 731 pickle.WriteString(std::string()); |
513 | 732 |
514 std::unique_ptr<SessionCommand> command( | 733 std::unique_ptr<SessionCommand> command( |
515 new SessionCommand(kCommandWindow, sizeof(payload))); | 734 new SessionCommand(kCommandWindow, pickle)); |
516 memcpy(command->contents(), &payload, sizeof(payload)); | |
517 return command; | 735 return command; |
518 } | 736 } |
519 | 737 |
520 // static | 738 // static |
521 std::unique_ptr<SessionCommand> | 739 std::unique_ptr<SessionCommand> |
522 PersistentTabRestoreService::Delegate::CreateSelectedNavigationInTabCommand( | 740 PersistentTabRestoreService::Delegate::CreateSelectedNavigationInTabCommand( |
523 SessionID::id_type tab_id, | 741 SessionID::id_type tab_id, |
524 int32_t index, | 742 int32_t index, |
525 base::Time timestamp) { | 743 base::Time timestamp) { |
526 SelectedNavigationInTabPayload2 payload; | 744 SelectedNavigationInTabPayload2 payload; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 current_tab = nullptr; | 829 current_tab = nullptr; |
612 current_window = nullptr; | 830 current_window = nullptr; |
613 | 831 |
614 RestoredEntryPayload payload; | 832 RestoredEntryPayload payload; |
615 if (!command.GetPayload(&payload, sizeof(payload))) | 833 if (!command.GetPayload(&payload, sizeof(payload))) |
616 return; | 834 return; |
617 RemoveEntryByID(payload, &entries); | 835 RemoveEntryByID(payload, &entries); |
618 break; | 836 break; |
619 } | 837 } |
620 | 838 |
| 839 case kCommandWindowDeprecated: |
621 case kCommandWindow: { | 840 case kCommandWindow: { |
622 WindowPayload2 payload; | 841 // Should never receive a window command while waiting for all the |
623 if (pending_window_tabs > 0) { | 842 // tabs in a window. |
624 // Should never receive a window command while waiting for all the | 843 if (pending_window_tabs > 0) |
625 // tabs in a window. | |
626 return; | 844 return; |
627 } | |
628 | 845 |
629 // Try the new payload first | 846 // Try to parse the command, and silently skip if it fails. |
630 if (!command.GetPayload(&payload, sizeof(payload))) { | 847 int32_t num_tabs = 0; |
631 // then the old payload | 848 SessionID::id_type window_id = 0; |
632 WindowPayload old_payload; | 849 std::unique_ptr<Window> window = |
633 if (!command.GetPayload(&old_payload, sizeof(old_payload))) | 850 CreateWindowEntryFromCommand(&command, &window_id, &num_tabs); |
634 return; | 851 if (!window) |
| 852 return; |
635 | 853 |
636 // Copy the old payload data to the new payload. | 854 // Should always have at least 1 tab. Likely indicates corruption. |
637 payload.window_id = old_payload.window_id; | 855 pending_window_tabs = num_tabs; |
638 payload.selected_tab_index = old_payload.selected_tab_index; | 856 if (pending_window_tabs <= 0) |
639 payload.num_tabs = old_payload.num_tabs; | 857 return; |
640 // Since we don't have a time use time 0 which is used to mark as an | |
641 // unknown timestamp. | |
642 payload.timestamp = 0; | |
643 } | |
644 | 858 |
645 pending_window_tabs = payload.num_tabs; | 859 RemoveEntryByID(window_id, &entries); |
646 if (pending_window_tabs <= 0) { | 860 current_window = window.get(); |
647 // Should always have at least 1 tab. Likely indicates corruption. | 861 entries.push_back(std::move(window)); |
648 return; | |
649 } | |
650 | |
651 RemoveEntryByID(payload.window_id, &entries); | |
652 | |
653 entries.push_back(base::MakeUnique<Window>()); | |
654 current_window = static_cast<Window*>(entries.back().get()); | |
655 current_window->selected_tab_index = payload.selected_tab_index; | |
656 current_window->timestamp = | |
657 base::Time::FromInternalValue(payload.timestamp); | |
658 break; | 862 break; |
659 } | 863 } |
660 | 864 |
661 case kCommandSelectedNavigationInTab: { | 865 case kCommandSelectedNavigationInTab: { |
662 SelectedNavigationInTabPayload2 payload; | 866 SelectedNavigationInTabPayload2 payload; |
663 if (!command.GetPayload(&payload, sizeof(payload))) { | 867 if (!command.GetPayload(&payload, sizeof(payload))) { |
664 SelectedNavigationInTabPayload old_payload; | 868 SelectedNavigationInTabPayload old_payload; |
665 if (!command.GetPayload(&old_payload, sizeof(old_payload))) | 869 if (!command.GetPayload(&old_payload, sizeof(old_payload))) |
666 return; | 870 return; |
667 payload.id = old_payload.id; | 871 payload.id = old_payload.id; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 } | 971 } |
768 | 972 |
769 default: | 973 default: |
770 // Unknown type, usually indicates corruption of file. Ignore it. | 974 // Unknown type, usually indicates corruption of file. Ignore it. |
771 return; | 975 return; |
772 } | 976 } |
773 } | 977 } |
774 | 978 |
775 // If there was corruption some of the entries won't be valid. | 979 // If there was corruption some of the entries won't be valid. |
776 ValidateAndDeleteEmptyEntries(&entries); | 980 ValidateAndDeleteEmptyEntries(&entries); |
777 | |
778 loaded_entries->swap(entries); | 981 loaded_entries->swap(entries); |
779 } | 982 } |
780 | 983 |
781 // static | 984 // static |
782 void PersistentTabRestoreService::Delegate::ValidateAndDeleteEmptyEntries( | 985 void PersistentTabRestoreService::Delegate::ValidateAndDeleteEmptyEntries( |
783 std::vector<std::unique_ptr<Entry>>* entries) { | 986 std::vector<std::unique_ptr<Entry>>* entries) { |
784 std::vector<std::unique_ptr<Entry>> valid_entries; | 987 std::vector<std::unique_ptr<Entry>> valid_entries; |
785 | 988 |
786 // Iterate from the back so that we keep the most recently closed entries. | 989 // Iterate from the back so that we keep the most recently closed entries. |
787 for (auto i = entries->rbegin(); i != entries->rend(); ++i) { | 990 for (auto i = entries->rbegin(); i != entries->rend(); ++i) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 tab.timestamp = base::Time(); | 1023 tab.timestamp = base::Time(); |
821 } | 1024 } |
822 } | 1025 } |
823 if (window->tabs.empty()) | 1026 if (window->tabs.empty()) |
824 return false; | 1027 return false; |
825 | 1028 |
826 window->selected_tab_index = | 1029 window->selected_tab_index = |
827 std::min(session_window->selected_tab_index, | 1030 std::min(session_window->selected_tab_index, |
828 static_cast<int>(window->tabs.size() - 1)); | 1031 static_cast<int>(window->tabs.size() - 1)); |
829 window->timestamp = base::Time(); | 1032 window->timestamp = base::Time(); |
| 1033 window->bounds = session_window->bounds; |
| 1034 window->show_state = session_window->show_state; |
| 1035 window->workspace = session_window->workspace; |
830 return true; | 1036 return true; |
831 } | 1037 } |
832 | 1038 |
833 void PersistentTabRestoreService::Delegate::LoadStateChanged() { | 1039 void PersistentTabRestoreService::Delegate::LoadStateChanged() { |
834 if ((load_state_ & (LOADED_LAST_TABS | LOADED_LAST_SESSION)) != | 1040 if ((load_state_ & (LOADED_LAST_TABS | LOADED_LAST_SESSION)) != |
835 (LOADED_LAST_TABS | LOADED_LAST_SESSION)) { | 1041 (LOADED_LAST_TABS | LOADED_LAST_SESSION)) { |
836 // Still waiting on previous session or previous tabs. | 1042 // Still waiting on previous session or previous tabs. |
837 return; | 1043 return; |
838 } | 1044 } |
839 | 1045 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 | 1164 |
959 TabRestoreService::Entries* PersistentTabRestoreService::mutable_entries() { | 1165 TabRestoreService::Entries* PersistentTabRestoreService::mutable_entries() { |
960 return &helper_.entries_; | 1166 return &helper_.entries_; |
961 } | 1167 } |
962 | 1168 |
963 void PersistentTabRestoreService::PruneEntries() { | 1169 void PersistentTabRestoreService::PruneEntries() { |
964 helper_.PruneEntries(); | 1170 helper_.PruneEntries(); |
965 } | 1171 } |
966 | 1172 |
967 } // namespace sessions | 1173 } // namespace sessions |
OLD | NEW |