Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Side by Side Diff: components/sessions/core/persistent_tab_restore_service.cc

Issue 2868983003: Ensure History > Recent Tabs restore preserves window disposition. (Closed)
Patch Set: Small fix to WindowCommandFields. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 // Erase it if it's our target. 129 // Erase it if it's our target.
129 if (tab.id == id) { 130 if (tab.id == id) {
130 window.tabs.erase(it); 131 window.tabs.erase(it);
131 return; 132 return;
132 } 133 }
133 } 134 }
134 } 135 }
135 } 136 }
136 } 137 }
137 138
139 // Converts a window show state to an integer. This function needs to be kept in
140 // sync with IntToWindowShowState below.
141 int WindowShowStateToInt(ui::WindowShowState show_state) {
sky 2017/07/11 20:28:09 optional: Maybe WindowShowStateToSerializedValue a
chrisha 2017/08/14 14:43:21 Done.
142 switch (show_state) {
143 case ui::SHOW_STATE_DEFAULT:
144 return 0;
sky 2017/07/11 20:28:09 Use a local enum with explicit values and a warnin
chrisha 2017/08/14 14:43:21 Done.
145 case ui::SHOW_STATE_NORMAL:
146 return 1;
147 case ui::SHOW_STATE_MINIMIZED:
148 return 2;
149 case ui::SHOW_STATE_MAXIMIZED:
150 return 3;
151 case ui::SHOW_STATE_INACTIVE:
152 return 4;
153 case ui::SHOW_STATE_FULLSCREEN:
154 return 5;
155 case ui::SHOW_STATE_END:
156 // This should never happen.
157 NOTREACHED();
158 return 6;
159 }
160 }
161
162 // Converts an integer to a window show state. Returns true on success, false
163 // otherwise.
164 bool IntToWindowShowState(int show_state_int, ui::WindowShowState* show_state) {
165 switch (show_state_int) {
166 case 0:
167 *show_state = ui::SHOW_STATE_DEFAULT;
168 return true;
169 case 1:
170 *show_state = ui::SHOW_STATE_NORMAL;
171 return true;
172 case 2:
173 *show_state = ui::SHOW_STATE_MINIMIZED;
174 return true;
175 case 3:
176 *show_state = ui::SHOW_STATE_MAXIMIZED;
177 return true;
178 case 4:
179 *show_state = ui::SHOW_STATE_INACTIVE;
180 return true;
181 case 5:
182 *show_state = ui::SHOW_STATE_FULLSCREEN;
183 return true;
184 default:
185 break;
186 }
187 return false;
188 }
189
190 // Superset of WindowPayloadObsolete/WindowPayloadObsolete2 and the other fields
191 // that can appear in the Pickle version of a Window command. This is used as a
192 // convenient destination for parsing the various fields in a WindowCommand.
193 struct WindowCommandFields {
194 // Fields in WindowPayloadObsolete/WindowPayloadObsolete2/Pickle:
195 int window_id = 0;
196 int selected_tab_index = 0;
197 int num_tabs = 0;
198
199 // Fields in WindowPayloadObsolete2/Pickle:
200 int64_t timestamp = 0;
201
202 // Fields in Pickle:
203 // Completely zeroed position/dimensions indicates that defaults should be
204 // used.
205 int window_x = 0;
206 int window_y = 0;
207 int window_width = 0;
208 int window_height = 0;
209 int window_show_state = 0;
210 std::string workspace;
211 };
212
213 std::unique_ptr<sessions::TabRestoreService::Window>
214 CreateWindowEntryFromCommand(const SessionCommand* command,
215 SessionID::id_type* window_id,
216 int32_t* num_tabs) {
217 bool parsed = false;
218
219 WindowCommandFields fields;
220 ui::WindowShowState show_state = ui::SHOW_STATE_DEFAULT;
221
222 // First try to parse the command as a pickle (the most modern version).
223 std::unique_ptr<base::Pickle> pickle(command->PayloadAsPickle());
sky 2017/07/11 20:28:09 I think this code would be less error prone if you
chrisha 2017/08/14 14:43:21 That's a good point. Done.
224 if (pickle.get()) {
225 base::PickleIterator it(*pickle);
226 WindowCommandFields parsed_fields;
227
228 // The first version of the pickle contains all of the following fields, so
229 // they should all successfully parse if the command is in fact a pickle.
230 if (it.ReadInt(&parsed_fields.window_id) &&
231 it.ReadInt(&parsed_fields.selected_tab_index) &&
232 it.ReadInt(&parsed_fields.num_tabs) &&
233 it.ReadInt64(&parsed_fields.timestamp) &&
234 it.ReadInt(&parsed_fields.window_x) &&
235 it.ReadInt(&parsed_fields.window_y) &&
236 it.ReadInt(&parsed_fields.window_width) &&
sky 2017/07/11 20:28:09 Make sure width/height are non-negative.
chrisha 2017/08/14 14:43:21 Done.
237 it.ReadInt(&parsed_fields.window_height) &&
238 it.ReadInt(&parsed_fields.window_show_state) &&
239 it.ReadString(&parsed_fields.workspace)) {
240 // Validate the window_show_state. If the entire pickle parsed but the
241 // show state is invalid then assume corruption.
242 if (!IntToWindowShowState(parsed_fields.window_show_state, &show_state))
243 return nullptr;
244
245 // New fields added to the pickle in later versions would be parsed here.
246
247 // Copy the parsed data.
248 fields = parsed_fields;
249 parsed = true;
250 }
251 }
252
253 // Next try to parse the command as a WindowPayloadObsolete2.
254 if (!parsed) {
255 WindowPayloadObsolete2 payload2;
256 if (command->GetPayload(&payload2, sizeof(payload2))) {
257 fields.window_id = payload2.window_id;
258 fields.selected_tab_index = payload2.selected_tab_index;
259 fields.num_tabs = payload2.num_tabs;
260 fields.timestamp = payload2.timestamp;
261 parsed = true;
262 }
263 }
264
265 // Finally, try the oldest WindowPayloadObsolete type.
266 if (!parsed) {
267 WindowPayloadObsolete payload;
268 if (command->GetPayload(&payload, sizeof(payload))) {
269 fields.window_id = payload.window_id;
270 fields.selected_tab_index = payload.selected_tab_index;
271 fields.num_tabs = payload.num_tabs;
272 parsed = true;
273 }
274 }
275
276 if (!parsed)
277 return nullptr;
278
279 // Create the Window entry.
280 std::unique_ptr<sessions::TabRestoreService::Window> window =
281 base::MakeUnique<sessions::TabRestoreService::Window>();
282 window->selected_tab_index = fields.selected_tab_index;
283 window->timestamp = base::Time::FromInternalValue(fields.timestamp);
284 window->selected_tab_index = fields.selected_tab_index;
285 window->timestamp = base::Time::FromInternalValue(fields.timestamp);
286 *window_id = static_cast<SessionID::id_type>(fields.window_id);
287 *num_tabs = fields.num_tabs;
288
289 // Set the bounds, show state and workspace if valid ones have been provided.
290 if (!(fields.window_x == 0 && fields.window_y == 0 &&
291 fields.window_width == 0 && fields.window_height == 0)) {
292 window->bounds.SetRect(fields.window_x, fields.window_y,
293 fields.window_width, fields.window_height);
294 // |show_state| was converted from window->show_state earlier during
295 // validation.
296 window->show_state = show_state;
297 window->workspace = std::move(fields.workspace);
298 }
299
300 return window;
301 }
302
138 } // namespace 303 } // namespace
139 304
140 // PersistentTabRestoreService::Delegate --------------------------------------- 305 // PersistentTabRestoreService::Delegate ---------------------------------------
141 306
142 // This restore service will create and own a BaseSessionService and implement 307 // This restore service will create and own a BaseSessionService and implement
143 // the required BaseSessionServiceDelegate. 308 // the required BaseSessionServiceDelegate.
144 class PersistentTabRestoreService::Delegate 309 class PersistentTabRestoreService::Delegate
145 : public BaseSessionServiceDelegate, 310 : public BaseSessionServiceDelegate,
146 public TabRestoreServiceHelper::Observer { 311 public TabRestoreServiceHelper::Observer {
147 public: 312 public:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 345
181 // Schedules the commands for a window close. 346 // Schedules the commands for a window close.
182 void ScheduleCommandsForWindow(const Window& window); 347 void ScheduleCommandsForWindow(const Window& window);
183 348
184 // Schedules the commands for a tab close. |selected_index| gives the index of 349 // Schedules the commands for a tab close. |selected_index| gives the index of
185 // the selected navigation. 350 // the selected navigation.
186 void ScheduleCommandsForTab(const Tab& tab, int selected_index); 351 void ScheduleCommandsForTab(const Tab& tab, int selected_index);
187 352
188 // Creates a window close command. 353 // Creates a window close command.
189 static std::unique_ptr<SessionCommand> CreateWindowCommand( 354 static std::unique_ptr<SessionCommand> CreateWindowCommand(
190 SessionID::id_type id, 355 SessionID::id_type window_id,
191 int selected_tab_index, 356 int selected_tab_index,
192 int num_tabs, 357 int num_tabs,
358 const gfx::Rect& bounds,
359 ui::WindowShowState show_state,
360 const std::string& workspace,
193 base::Time timestamp); 361 base::Time timestamp);
194 362
195 // Creates a tab close command. 363 // Creates a tab close command.
196 static std::unique_ptr<SessionCommand> CreateSelectedNavigationInTabCommand( 364 static std::unique_ptr<SessionCommand> CreateSelectedNavigationInTabCommand(
197 SessionID::id_type tab_id, 365 SessionID::id_type tab_id,
198 int32_t index, 366 int32_t index,
199 base::Time timestamp); 367 base::Time timestamp);
200 368
201 // Creates a restore command. 369 // Creates a restore command.
202 static std::unique_ptr<SessionCommand> CreateRestoredEntryCommand( 370 static std::unique_ptr<SessionCommand> CreateRestoredEntryCommand(
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 valid_tab_count++; 596 valid_tab_count++;
429 } else if (static_cast<int>(i) < selected_tab) { 597 } else if (static_cast<int>(i) < selected_tab) {
430 real_selected_tab--; 598 real_selected_tab--;
431 } 599 }
432 } 600 }
433 if (valid_tab_count == 0) 601 if (valid_tab_count == 0)
434 return; // No tabs to persist. 602 return; // No tabs to persist.
435 603
436 base_session_service_->ScheduleCommand(CreateWindowCommand( 604 base_session_service_->ScheduleCommand(CreateWindowCommand(
437 window.id, std::min(real_selected_tab, valid_tab_count - 1), 605 window.id, std::min(real_selected_tab, valid_tab_count - 1),
438 valid_tab_count, window.timestamp)); 606 valid_tab_count, window.bounds, window.show_state, window.workspace,
607 window.timestamp));
439 608
440 if (!window.app_name.empty()) { 609 if (!window.app_name.empty()) {
441 base_session_service_->ScheduleCommand(CreateSetWindowAppNameCommand( 610 base_session_service_->ScheduleCommand(CreateSetWindowAppNameCommand(
442 kCommandSetWindowAppName, window.id, window.app_name)); 611 kCommandSetWindowAppName, window.id, window.app_name));
443 } 612 }
444 613
445 for (size_t i = 0; i < window.tabs.size(); ++i) { 614 for (size_t i = 0; i < window.tabs.size(); ++i) {
446 int selected_index = GetSelectedNavigationIndexToPersist(*window.tabs[i]); 615 int selected_index = GetSelectedNavigationIndexToPersist(*window.tabs[i]);
447 if (selected_index != -1) 616 if (selected_index != -1)
448 ScheduleCommandsForTab(*window.tabs[i], selected_index); 617 ScheduleCommandsForTab(*window.tabs[i], selected_index);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, 666 CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation,
498 tab.id, 667 tab.id,
499 navigations[i])); 668 navigations[i]));
500 } 669 }
501 } 670 }
502 } 671 }
503 672
504 // static 673 // static
505 std::unique_ptr<SessionCommand> 674 std::unique_ptr<SessionCommand>
506 PersistentTabRestoreService::Delegate::CreateWindowCommand( 675 PersistentTabRestoreService::Delegate::CreateWindowCommand(
507 SessionID::id_type id, 676 SessionID::id_type window_id,
508 int selected_tab_index, 677 int selected_tab_index,
509 int num_tabs, 678 int num_tabs,
679 const gfx::Rect& bounds,
680 ui::WindowShowState show_state,
681 const std::string& workspace,
510 base::Time timestamp) { 682 base::Time timestamp) {
511 WindowPayload2 payload; 683 static_assert(sizeof(SessionID::id_type) == sizeof(int),
512 // |timestamp| is aligned on a 16 byte boundary, leaving 4 bytes of 684 "SessionID::id_type has changed size.");
513 // uninitialized memory in the struct. 685
514 memset(&payload, 0, sizeof(payload)); 686 // Use a pickle to handle marshaling as this command contains variable-length
515 payload.window_id = id; 687 // content.
516 payload.selected_tab_index = selected_tab_index; 688 base::Pickle pickle;
517 payload.num_tabs = num_tabs; 689 pickle.WriteInt(static_cast<int>(window_id));
518 payload.timestamp = timestamp.ToInternalValue(); 690 pickle.WriteInt(selected_tab_index);
691 pickle.WriteInt(num_tabs);
692 pickle.WriteInt64(timestamp.ToInternalValue());
693 pickle.WriteInt(bounds.x());
694 pickle.WriteInt(bounds.y());
695 pickle.WriteInt(bounds.width());
696 pickle.WriteInt(bounds.height());
697 pickle.WriteInt(WindowShowStateToInt(show_state));
698
699 // Enforce a maximum length on workspace names. A common size is 32 bytes for
700 // GUIDs.
701 if (workspace.size() <= 128)
702 pickle.WriteString(workspace);
703 else
704 pickle.WriteString(std::string());
519 705
520 std::unique_ptr<SessionCommand> command( 706 std::unique_ptr<SessionCommand> command(
521 new SessionCommand(kCommandWindow, sizeof(payload))); 707 new SessionCommand(kCommandWindow, pickle));
522 memcpy(command->contents(), &payload, sizeof(payload));
523 return command; 708 return command;
524 } 709 }
525 710
526 // static 711 // static
527 std::unique_ptr<SessionCommand> 712 std::unique_ptr<SessionCommand>
528 PersistentTabRestoreService::Delegate::CreateSelectedNavigationInTabCommand( 713 PersistentTabRestoreService::Delegate::CreateSelectedNavigationInTabCommand(
529 SessionID::id_type tab_id, 714 SessionID::id_type tab_id,
530 int32_t index, 715 int32_t index,
531 base::Time timestamp) { 716 base::Time timestamp) {
532 SelectedNavigationInTabPayload2 payload; 717 SelectedNavigationInTabPayload2 payload;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 current_window = nullptr; 803 current_window = nullptr;
619 804
620 RestoredEntryPayload payload; 805 RestoredEntryPayload payload;
621 if (!command.GetPayload(&payload, sizeof(payload))) 806 if (!command.GetPayload(&payload, sizeof(payload)))
622 return; 807 return;
623 RemoveEntryByID(payload, &entries); 808 RemoveEntryByID(payload, &entries);
624 break; 809 break;
625 } 810 }
626 811
627 case kCommandWindow: { 812 case kCommandWindow: {
628 WindowPayload2 payload; 813 // Should never receive a window command while waiting for all the
629 if (pending_window_tabs > 0) { 814 // tabs in a window.
630 // Should never receive a window command while waiting for all the 815 if (pending_window_tabs > 0)
631 // tabs in a window.
632 return; 816 return;
633 }
634 817
635 // Try the new payload first 818 // Try to parse the command, and silently skip if it fails.
636 if (!command.GetPayload(&payload, sizeof(payload))) { 819 int32_t num_tabs = 0;
637 // then the old payload 820 SessionID::id_type window_id = 0;
638 WindowPayload old_payload; 821 std::unique_ptr<Window> window =
639 if (!command.GetPayload(&old_payload, sizeof(old_payload))) 822 CreateWindowEntryFromCommand(&command, &window_id, &num_tabs);
640 return; 823 if (!window)
824 return;
641 825
642 // Copy the old payload data to the new payload. 826 // Should always have at least 1 tab. Likely indicates corruption.
643 payload.window_id = old_payload.window_id; 827 pending_window_tabs = num_tabs;
644 payload.selected_tab_index = old_payload.selected_tab_index; 828 if (pending_window_tabs <= 0)
645 payload.num_tabs = old_payload.num_tabs; 829 return;
646 // Since we don't have a time use time 0 which is used to mark as an
647 // unknown timestamp.
648 payload.timestamp = 0;
649 }
650 830
651 pending_window_tabs = payload.num_tabs; 831 RemoveEntryByID(window_id, &entries);
652 if (pending_window_tabs <= 0) { 832 current_window = window.get();
653 // Should always have at least 1 tab. Likely indicates corruption. 833 entries.push_back(std::move(window));
654 return;
655 }
656
657 RemoveEntryByID(payload.window_id, &entries);
658
659 entries.push_back(base::MakeUnique<Window>());
660 current_window = static_cast<Window*>(entries.back().get());
661 current_window->selected_tab_index = payload.selected_tab_index;
662 current_window->timestamp =
663 base::Time::FromInternalValue(payload.timestamp);
664 break; 834 break;
665 } 835 }
666 836
667 case kCommandSelectedNavigationInTab: { 837 case kCommandSelectedNavigationInTab: {
668 SelectedNavigationInTabPayload2 payload; 838 SelectedNavigationInTabPayload2 payload;
669 if (!command.GetPayload(&payload, sizeof(payload))) { 839 if (!command.GetPayload(&payload, sizeof(payload))) {
670 SelectedNavigationInTabPayload old_payload; 840 SelectedNavigationInTabPayload old_payload;
671 if (!command.GetPayload(&old_payload, sizeof(old_payload))) 841 if (!command.GetPayload(&old_payload, sizeof(old_payload)))
672 return; 842 return;
673 payload.id = old_payload.id; 843 payload.id = old_payload.id;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 } 943 }
774 944
775 default: 945 default:
776 // Unknown type, usually indicates corruption of file. Ignore it. 946 // Unknown type, usually indicates corruption of file. Ignore it.
777 return; 947 return;
778 } 948 }
779 } 949 }
780 950
781 // If there was corruption some of the entries won't be valid. 951 // If there was corruption some of the entries won't be valid.
782 ValidateAndDeleteEmptyEntries(&entries); 952 ValidateAndDeleteEmptyEntries(&entries);
783
784 loaded_entries->swap(entries); 953 loaded_entries->swap(entries);
785 } 954 }
786 955
787 // static 956 // static
788 void PersistentTabRestoreService::Delegate::ValidateAndDeleteEmptyEntries( 957 void PersistentTabRestoreService::Delegate::ValidateAndDeleteEmptyEntries(
789 std::vector<std::unique_ptr<Entry>>* entries) { 958 std::vector<std::unique_ptr<Entry>>* entries) {
790 std::vector<std::unique_ptr<Entry>> valid_entries; 959 std::vector<std::unique_ptr<Entry>> valid_entries;
791 960
792 // Iterate from the back so that we keep the most recently closed entries. 961 // Iterate from the back so that we keep the most recently closed entries.
793 for (auto i = entries->rbegin(); i != entries->rend(); ++i) { 962 for (auto i = entries->rbegin(); i != entries->rend(); ++i) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 tab.timestamp = base::Time(); 995 tab.timestamp = base::Time();
827 } 996 }
828 } 997 }
829 if (window->tabs.empty()) 998 if (window->tabs.empty())
830 return false; 999 return false;
831 1000
832 window->selected_tab_index = 1001 window->selected_tab_index =
833 std::min(session_window->selected_tab_index, 1002 std::min(session_window->selected_tab_index,
834 static_cast<int>(window->tabs.size() - 1)); 1003 static_cast<int>(window->tabs.size() - 1));
835 window->timestamp = base::Time(); 1004 window->timestamp = base::Time();
1005 window->bounds = session_window->bounds;
1006 window->show_state = session_window->show_state;
1007 window->workspace = session_window->workspace;
836 return true; 1008 return true;
837 } 1009 }
838 1010
839 void PersistentTabRestoreService::Delegate::LoadStateChanged() { 1011 void PersistentTabRestoreService::Delegate::LoadStateChanged() {
840 if ((load_state_ & (LOADED_LAST_TABS | LOADED_LAST_SESSION)) != 1012 if ((load_state_ & (LOADED_LAST_TABS | LOADED_LAST_SESSION)) !=
841 (LOADED_LAST_TABS | LOADED_LAST_SESSION)) { 1013 (LOADED_LAST_TABS | LOADED_LAST_SESSION)) {
842 // Still waiting on previous session or previous tabs. 1014 // Still waiting on previous session or previous tabs.
843 return; 1015 return;
844 } 1016 }
845 1017
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 1136
965 TabRestoreService::Entries* PersistentTabRestoreService::mutable_entries() { 1137 TabRestoreService::Entries* PersistentTabRestoreService::mutable_entries() {
966 return &helper_.entries_; 1138 return &helper_.entries_;
967 } 1139 }
968 1140
969 void PersistentTabRestoreService::PruneEntries() { 1141 void PersistentTabRestoreService::PruneEntries() {
970 helper_.PruneEntries(); 1142 helper_.PruneEntries();
971 } 1143 }
972 1144
973 } // namespace sessions 1145 } // namespace sessions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698