OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 "chrome/browser/sessions/persistent_tab_restore_service.h" | 5 #include "chrome/browser/sessions/persistent_tab_restore_service.h" |
6 | 6 |
7 #include <cstring> // memcpy | 7 #include <cstring> // memcpy |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/file_path.h" | 13 #include "base/file_path.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
16 #include "base/memory/scoped_vector.h" | 16 #include "base/memory/scoped_vector.h" |
17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
18 #include "base/time.h" | 18 #include "base/time.h" |
19 #include "chrome/browser/common/cancelable_request.h" | 19 #include "chrome/browser/common/cancelable_request.h" |
20 #include "chrome/browser/profiles/profile.h" | 20 #include "chrome/browser/profiles/profile.h" |
21 #include "chrome/browser/sessions/base_session_service.h" | 21 #include "chrome/browser/sessions/base_session_service.h" |
22 #include "chrome/browser/sessions/session_command.h" | 22 #include "chrome/browser/sessions/session_command.h" |
23 #include "chrome/browser/sessions/session_service.h" | 23 #include "chrome/browser/sessions/session_service.h" |
24 #include "chrome/browser/sessions/session_service_factory.h" | 24 #include "chrome/browser/sessions/session_service_factory.h" |
25 #include "chrome/browser/sessions/tab_restore_service_factory.h" | 25 #include "chrome/browser/sessions/tab_restore_service_factory.h" |
| 26 #include "chrome/common/cancelable_task_tracker.h" |
26 #include "content/public/browser/session_storage_namespace.h" | 27 #include "content/public/browser/session_storage_namespace.h" |
27 | 28 |
28 namespace { | 29 namespace { |
29 | 30 |
30 // Only written if the tab is pinned. | 31 // Only written if the tab is pinned. |
31 typedef bool PinnedStatePayload; | 32 typedef bool PinnedStatePayload; |
32 | 33 |
33 typedef int32 RestoredEntryPayload; | 34 typedef int32 RestoredEntryPayload; |
34 | 35 |
35 typedef std::map<SessionID::id_type, TabRestoreService::Entry*> IDToEntry; | 36 typedef std::map<SessionID::id_type, TabRestoreService::Entry*> IDToEntry; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 | 172 |
172 // Returns the index to persist as the selected index. This is the same as | 173 // Returns the index to persist as the selected index. This is the same as |
173 // |tab.current_navigation_index| unless the entry at | 174 // |tab.current_navigation_index| unless the entry at |
174 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if no | 175 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if no |
175 // valid navigation to persist. | 176 // valid navigation to persist. |
176 int GetSelectedNavigationIndexToPersist(const Tab& tab); | 177 int GetSelectedNavigationIndexToPersist(const Tab& tab); |
177 | 178 |
178 // Invoked when we've loaded the session commands that identify the previously | 179 // Invoked when we've loaded the session commands that identify the previously |
179 // closed tabs. This creates entries, adds them to staging_entries_, and | 180 // closed tabs. This creates entries, adds them to staging_entries_, and |
180 // invokes LoadState. | 181 // invokes LoadState. |
181 void OnGotLastSessionCommands( | 182 void OnGotLastSessionCommands(ScopedVector<SessionCommand> commands); |
182 Handle handle, | |
183 scoped_refptr<InternalGetCommandsRequest> request); | |
184 | 183 |
185 // Populates |loaded_entries| with Entries from |request|. | 184 // Populates |loaded_entries| with Entries from |commands|. |
186 void CreateEntriesFromCommands( | 185 void CreateEntriesFromCommands(const std::vector<SessionCommand*>& commands, |
187 scoped_refptr<InternalGetCommandsRequest> request, | 186 std::vector<Entry*>* loaded_entries); |
188 std::vector<Entry*>* loaded_entries); | |
189 | 187 |
190 // Validates all entries in |entries|, deleting any with no navigations. This | 188 // Validates all entries in |entries|, deleting any with no navigations. This |
191 // also deletes any entries beyond the max number of entries we can hold. | 189 // also deletes any entries beyond the max number of entries we can hold. |
192 static void ValidateAndDeleteEmptyEntries(std::vector<Entry*>* entries); | 190 static void ValidateAndDeleteEmptyEntries(std::vector<Entry*>* entries); |
193 | 191 |
194 // Callback from SessionService when we've received the windows from the | 192 // Callback from SessionService when we've received the windows from the |
195 // previous session. This creates and add entries to |staging_entries_| and | 193 // previous session. This creates and add entries to |staging_entries_| and |
196 // invokes LoadStateChanged. |ignored_active_window| is ignored because we | 194 // invokes LoadStateChanged. |ignored_active_window| is ignored because we |
197 // don't need to restore activation. | 195 // don't need to restore activation. |
198 void OnGotPreviousSession(Handle handle, | 196 void OnGotPreviousSession(ScopedVector<SessionWindow> windows, |
199 std::vector<SessionWindow*>* windows, | |
200 SessionID::id_type ignored_active_window); | 197 SessionID::id_type ignored_active_window); |
201 | 198 |
202 // Converts a SessionWindow into a Window, returning true on success. We use 0 | 199 // Converts a SessionWindow into a Window, returning true on success. We use 0 |
203 // as the timestamp here since we do not know when the window/tab was closed. | 200 // as the timestamp here since we do not know when the window/tab was closed. |
204 static bool ConvertSessionWindowToWindow(SessionWindow* session_window, | 201 static bool ConvertSessionWindowToWindow(SessionWindow* session_window, |
205 Window* window); | 202 Window* window); |
206 | 203 |
207 // Invoked when previous tabs or session is loaded. If both have finished | 204 // Invoked when previous tabs or session is loaded. If both have finished |
208 // loading the entries in |staging_entries_| are added to entries and | 205 // loading the entries in |staging_entries_| are added to entries and |
209 // observers are notified. | 206 // observers are notified. |
(...skipping 16 matching lines...) Expand all Loading... |
226 int entries_written_; | 223 int entries_written_; |
227 | 224 |
228 // Whether we've loaded the last session. | 225 // Whether we've loaded the last session. |
229 int load_state_; | 226 int load_state_; |
230 | 227 |
231 // Results from previously closed tabs/sessions is first added here. When the | 228 // Results from previously closed tabs/sessions is first added here. When the |
232 // results from both us and the session restore service have finished loading | 229 // results from both us and the session restore service have finished loading |
233 // LoadStateChanged is invoked, which adds these entries to entries_. | 230 // LoadStateChanged is invoked, which adds these entries to entries_. |
234 std::vector<Entry*> staging_entries_; | 231 std::vector<Entry*> staging_entries_; |
235 | 232 |
236 // Used when loading previous tabs/session. | 233 // Used when loading previous tabs/session and open tabs/session. |
237 CancelableRequestConsumer load_consumer_; | 234 CancelableTaskTracker cancelable_task_tracker_; |
238 | |
239 // Used when loading open tabs/session when recovering from a crash. | |
240 CancelableRequestConsumer crash_consumer_; | |
241 | 235 |
242 DISALLOW_COPY_AND_ASSIGN(Delegate); | 236 DISALLOW_COPY_AND_ASSIGN(Delegate); |
243 }; | 237 }; |
244 | 238 |
245 PersistentTabRestoreService::Delegate::Delegate(Profile* profile) | 239 PersistentTabRestoreService::Delegate::Delegate(Profile* profile) |
246 : BaseSessionService(BaseSessionService::TAB_RESTORE, profile, | 240 : BaseSessionService(BaseSessionService::TAB_RESTORE, profile, |
247 FilePath()), | 241 FilePath()), |
248 tab_restore_service_helper_(NULL), | 242 tab_restore_service_helper_(NULL), |
249 entries_to_write_(0), | 243 entries_to_write_(0), |
250 entries_written_(0), | 244 entries_written_(0), |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 SessionServiceFactory::GetForProfile(profile()); | 335 SessionServiceFactory::GetForProfile(profile()); |
342 Profile::ExitType exit_type = profile()->GetLastSessionExitType(); | 336 Profile::ExitType exit_type = profile()->GetLastSessionExitType(); |
343 if (!profile()->restored_last_session() && session_service && | 337 if (!profile()->restored_last_session() && session_service && |
344 (exit_type == Profile::EXIT_CRASHED || | 338 (exit_type == Profile::EXIT_CRASHED || |
345 exit_type == Profile::EXIT_SESSION_ENDED)) { | 339 exit_type == Profile::EXIT_SESSION_ENDED)) { |
346 // The previous session crashed and wasn't restored, or was a forced | 340 // The previous session crashed and wasn't restored, or was a forced |
347 // shutdown. Both of which won't have notified us of the browser close so | 341 // shutdown. Both of which won't have notified us of the browser close so |
348 // that we need to load the windows from session service (which will have | 342 // that we need to load the windows from session service (which will have |
349 // saved them). | 343 // saved them). |
350 session_service->GetLastSession( | 344 session_service->GetLastSession( |
351 &crash_consumer_, | 345 base::Bind(&Delegate::OnGotPreviousSession, base::Unretained(this)), |
352 base::Bind(&Delegate::OnGotPreviousSession, base::Unretained(this))); | 346 &cancelable_task_tracker_); |
353 } else { | 347 } else { |
354 load_state_ |= LOADED_LAST_SESSION; | 348 load_state_ |= LOADED_LAST_SESSION; |
355 } | 349 } |
356 #endif | 350 #endif |
357 | 351 |
358 // Request the tabs closed in the last session. If the last session crashed, | 352 // Request the tabs closed in the last session. If the last session crashed, |
359 // this won't contain the tabs/window that were open at the point of the | 353 // this won't contain the tabs/window that were open at the point of the |
360 // crash (the call to GetLastSession above requests those). | 354 // crash (the call to GetLastSession above requests those). |
361 ScheduleGetLastSessionCommands( | 355 ScheduleGetLastSessionCommands( |
362 new InternalGetCommandsRequest( | 356 base::Bind(&Delegate::OnGotLastSessionCommands, base::Unretained(this)), |
363 base::Bind(&Delegate::OnGotLastSessionCommands, | 357 &cancelable_task_tracker_); |
364 base::Unretained(this))), | |
365 &load_consumer_); | |
366 } | 358 } |
367 | 359 |
368 bool PersistentTabRestoreService::Delegate::IsLoaded() const { | 360 bool PersistentTabRestoreService::Delegate::IsLoaded() const { |
369 return !(load_state_ & (NOT_LOADED | LOADING)); | 361 return !(load_state_ & (NOT_LOADED | LOADING)); |
370 } | 362 } |
371 | 363 |
372 // static | 364 // static |
373 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( | 365 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( |
374 std::vector<SessionWindow*>* windows, | 366 std::vector<SessionWindow*>* windows, |
375 std::vector<Entry*>* entries) { | 367 std::vector<Entry*>* entries) { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 selected_index = tab.current_navigation_index + 1; | 535 selected_index = tab.current_navigation_index + 1; |
544 while (selected_index < max_index && | 536 while (selected_index < max_index && |
545 !ShouldTrackEntry(navigations[selected_index].virtual_url())) { | 537 !ShouldTrackEntry(navigations[selected_index].virtual_url())) { |
546 selected_index++; | 538 selected_index++; |
547 } | 539 } |
548 | 540 |
549 return (selected_index == max_index) ? -1 : selected_index; | 541 return (selected_index == max_index) ? -1 : selected_index; |
550 } | 542 } |
551 | 543 |
552 void PersistentTabRestoreService::Delegate::OnGotLastSessionCommands( | 544 void PersistentTabRestoreService::Delegate::OnGotLastSessionCommands( |
553 Handle handle, | 545 ScopedVector<SessionCommand> commands) { |
554 scoped_refptr<InternalGetCommandsRequest> request) { | |
555 std::vector<Entry*> entries; | 546 std::vector<Entry*> entries; |
556 CreateEntriesFromCommands(request, &entries); | 547 CreateEntriesFromCommands(commands.get(), &entries); |
557 // Closed tabs always go to the end. | 548 // Closed tabs always go to the end. |
558 staging_entries_.insert(staging_entries_.end(), entries.begin(), | 549 staging_entries_.insert(staging_entries_.end(), entries.begin(), |
559 entries.end()); | 550 entries.end()); |
560 load_state_ |= LOADED_LAST_TABS; | 551 load_state_ |= LOADED_LAST_TABS; |
561 LoadStateChanged(); | 552 LoadStateChanged(); |
562 } | 553 } |
563 | 554 |
564 void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( | 555 void PersistentTabRestoreService::Delegate::CreateEntriesFromCommands( |
565 scoped_refptr<InternalGetCommandsRequest> request, | 556 const std::vector<SessionCommand*>& commands, |
566 std::vector<Entry*>* loaded_entries) { | 557 std::vector<Entry*>* loaded_entries) { |
567 if (request->canceled() || | 558 if (tab_restore_service_helper_->entries().size() == kMaxEntries) |
568 tab_restore_service_helper_->entries().size() == kMaxEntries) | |
569 return; | 559 return; |
570 | 560 |
571 std::vector<SessionCommand*>& commands = request->commands; | |
572 // Iterate through the commands populating entries and id_to_entry. | 561 // Iterate through the commands populating entries and id_to_entry. |
573 ScopedVector<Entry> entries; | 562 ScopedVector<Entry> entries; |
574 IDToEntry id_to_entry; | 563 IDToEntry id_to_entry; |
575 // If non-null we're processing the navigations of this tab. | 564 // If non-null we're processing the navigations of this tab. |
576 Tab* current_tab = NULL; | 565 Tab* current_tab = NULL; |
577 // If non-null we're processing the tabs of this window. | 566 // If non-null we're processing the tabs of this window. |
578 Window* current_window = NULL; | 567 Window* current_window = NULL; |
579 // If > 0, we've gotten a window command but not all the tabs yet. | 568 // If > 0, we've gotten a window command but not all the tabs yet. |
580 int pending_window_tabs = 0; | 569 int pending_window_tabs = 0; |
581 for (std::vector<SessionCommand*>::const_iterator i = commands.begin(); | 570 for (std::vector<SessionCommand*>::const_iterator i = commands.begin(); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 invalid_entries.push_back(*i); | 762 invalid_entries.push_back(*i); |
774 } | 763 } |
775 // NOTE: at this point the entries are ordered with newest at the front. | 764 // NOTE: at this point the entries are ordered with newest at the front. |
776 entries->swap(valid_entries); | 765 entries->swap(valid_entries); |
777 | 766 |
778 // Delete the remaining entries. | 767 // Delete the remaining entries. |
779 STLDeleteElements(&invalid_entries); | 768 STLDeleteElements(&invalid_entries); |
780 } | 769 } |
781 | 770 |
782 void PersistentTabRestoreService::Delegate::OnGotPreviousSession( | 771 void PersistentTabRestoreService::Delegate::OnGotPreviousSession( |
783 Handle handle, | 772 ScopedVector<SessionWindow> windows, |
784 std::vector<SessionWindow*>* windows, | |
785 SessionID::id_type ignored_active_window) { | 773 SessionID::id_type ignored_active_window) { |
786 std::vector<Entry*> entries; | 774 std::vector<Entry*> entries; |
787 CreateEntriesFromWindows(windows, &entries); | 775 CreateEntriesFromWindows(&windows.get(), &entries); |
788 // Previous session tabs go first. | 776 // Previous session tabs go first. |
789 staging_entries_.insert(staging_entries_.begin(), entries.begin(), | 777 staging_entries_.insert(staging_entries_.begin(), entries.begin(), |
790 entries.end()); | 778 entries.end()); |
791 load_state_ |= LOADED_LAST_SESSION; | 779 load_state_ |= LOADED_LAST_SESSION; |
792 LoadStateChanged(); | 780 LoadStateChanged(); |
793 } | 781 } |
794 | 782 |
795 bool PersistentTabRestoreService::Delegate::ConvertSessionWindowToWindow( | 783 bool PersistentTabRestoreService::Delegate::ConvertSessionWindowToWindow( |
796 SessionWindow* session_window, | 784 SessionWindow* session_window, |
797 Window* window) { | 785 Window* window) { |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 } | 974 } |
987 | 975 |
988 void PersistentTabRestoreService::PruneEntries() { | 976 void PersistentTabRestoreService::PruneEntries() { |
989 helper_.PruneEntries(); | 977 helper_.PruneEntries(); |
990 } | 978 } |
991 | 979 |
992 ProfileKeyedService* TabRestoreServiceFactory::BuildServiceInstanceFor( | 980 ProfileKeyedService* TabRestoreServiceFactory::BuildServiceInstanceFor( |
993 Profile* profile) const { | 981 Profile* profile) const { |
994 return new PersistentTabRestoreService(profile, NULL); | 982 return new PersistentTabRestoreService(profile, NULL); |
995 } | 983 } |
OLD | NEW |