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