| 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 |