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

Side by Side Diff: chrome/browser/sessions/tab_restore_service.cc

Issue 14172: Makes the tab restore service contain any windows that were open at... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 <algorithm> 5 #include <algorithm>
6 #include <iterator> 6 #include <iterator>
7 7
8 #include "chrome/browser/sessions/tab_restore_service.h" 8 #include "chrome/browser/sessions/tab_restore_service.h"
9 9
10 #include "chrome/browser/browser_list.h" 10 #include "chrome/browser/browser_list.h"
11 #include "chrome/browser/navigation_controller.h" 11 #include "chrome/browser/navigation_controller.h"
12 #include "chrome/browser/navigation_entry.h" 12 #include "chrome/browser/navigation_entry.h"
13 #include "chrome/browser/profile.h" 13 #include "chrome/browser/profile.h"
14 #include "chrome/browser/sessions/session_backend.h" 14 #include "chrome/browser/sessions/session_backend.h"
15 #include "chrome/browser/sessions/session_service.h"
15 #include "chrome/common/scoped_vector.h" 16 #include "chrome/common/scoped_vector.h"
16 #include "chrome/common/stl_util-inl.h" 17 #include "chrome/common/stl_util-inl.h"
17 18
18 using base::Time; 19 using base::Time;
19 20
20 // Entry ---------------------------------------------------------------------- 21 // Entry ----------------------------------------------------------------------
21 22
22 // ID of the next Entry. 23 // ID of the next Entry.
23 static SessionID::id_type next_entry_id = 1; 24 static SessionID::id_type next_entry_id = 1;
24 25
25 TabRestoreService::Entry::Entry() : id(next_entry_id++), type(TAB) {} 26 TabRestoreService::Entry::Entry() : id(next_entry_id++), type(TAB) {}
26 27
27 TabRestoreService::Entry::Entry(Type type) : id(next_entry_id++), type(type) {} 28 TabRestoreService::Entry::Entry(Type type) : id(next_entry_id++), type(type) {}
28 29
29 // TabRestoreService ---------------------------------------------------------- 30 // TabRestoreService ----------------------------------------------------------
30 31
31 // Max number of entries we'll keep around. 32 // static
32 static const size_t kMaxEntries = 10; 33 const size_t TabRestoreService::kMaxEntries = 10;
33 34
34 // Identifier for commands written to file. 35 // Identifier for commands written to file.
35 // The ordering in the file is as follows: 36 // The ordering in the file is as follows:
36 // . When the user closes a tab a command of type 37 // . When the user closes a tab a command of type
37 // kCommandSelectedNavigationInTab is written identifying the tab and 38 // kCommandSelectedNavigationInTab is written identifying the tab and
38 // the selected index. This is followed by any number of 39 // the selected index. This is followed by any number of
39 // kCommandUpdateTabNavigation commands (1 per navigation entry). 40 // kCommandUpdateTabNavigation commands (1 per navigation entry).
40 // . When the user closes a window a kCommandSelectedNavigationInTab command 41 // . When the user closes a window a kCommandSelectedNavigationInTab command
41 // is written out and followed by n tab closed sequences (as previoulsy 42 // is written out and followed by n tab closed sequences (as previoulsy
42 // described). 43 // described).
(...skipping 14 matching lines...) Expand all
57 58
58 typedef int32 RestoredEntryPayload; 59 typedef int32 RestoredEntryPayload;
59 60
60 // Payload used for the start of a window close. 61 // Payload used for the start of a window close.
61 struct WindowPayload { 62 struct WindowPayload {
62 SessionID::id_type window_id; 63 SessionID::id_type window_id;
63 int32 selected_tab_index; 64 int32 selected_tab_index;
64 int32 num_tabs; 65 int32 num_tabs;
65 }; 66 };
66 67
67 // Paylowed used for the start of a tab close. 68 // Payload used for the start of a tab close.
68 struct SelectedNavigationInTabPayload { 69 struct SelectedNavigationInTabPayload {
69 SessionID::id_type id; 70 SessionID::id_type id;
70 int32 index; 71 int32 index;
71 }; 72 };
72 73
73 typedef std::map<SessionID::id_type, TabRestoreService::Entry*> IDToEntry; 74 typedef std::map<SessionID::id_type, TabRestoreService::Entry*> IDToEntry;
74 75
75 // If |id_to_entry| contains an entry for |id| the corresponding entry is 76 // If |id_to_entry| contains an entry for |id| the corresponding entry is
76 // deleted and removed from both |id_to_entry| and |entries|. This is used 77 // deleted and removed from both |id_to_entry| and |entries|. This is used
77 // when creating entries from the backend file. 78 // when creating entries from the backend file.
78 void RemoveEntryByID(SessionID::id_type id, 79 void RemoveEntryByID(SessionID::id_type id,
79 IDToEntry* id_to_entry, 80 IDToEntry* id_to_entry,
80 std::vector<TabRestoreService::Entry*>* entries) { 81 std::vector<TabRestoreService::Entry*>* entries) {
81 IDToEntry::iterator i = id_to_entry->find(id); 82 IDToEntry::iterator i = id_to_entry->find(id);
82 if (i == id_to_entry->end()) 83 if (i == id_to_entry->end())
83 return; 84 return;
84 85
85 entries->erase(std::find(entries->begin(), entries->end(), i->second)); 86 entries->erase(std::find(entries->begin(), entries->end(), i->second));
86 delete i->second; 87 delete i->second;
87 id_to_entry->erase(i); 88 id_to_entry->erase(i);
88 } 89 }
89 90
90 } // namespace 91 } // namespace
91 92
92 TabRestoreService::TabRestoreService(Profile* profile) 93 TabRestoreService::TabRestoreService(Profile* profile)
93 : BaseSessionService(BaseSessionService::TAB_RESTORE, profile, 94 : BaseSessionService(BaseSessionService::TAB_RESTORE, profile,
94 std::wstring()), 95 std::wstring()),
95 loaded_last_session_(false), 96 load_state_(NOT_LOADED),
96 restoring_(false), 97 restoring_(false),
97 reached_max_(false), 98 reached_max_(false),
98 entries_to_write_(0), 99 entries_to_write_(0),
99 entries_written_(0) { 100 entries_written_(0) {
100 } 101 }
101 102
102 TabRestoreService::~TabRestoreService() { 103 TabRestoreService::~TabRestoreService() {
103 if (backend()) 104 if (backend())
104 Save(); 105 Save();
105 106
106 FOR_EACH_OBSERVER(Observer, observer_list_, TabRestoreServiceDestroyed(this)); 107 FOR_EACH_OBSERVER(Observer, observer_list_, TabRestoreServiceDestroyed(this));
107 STLDeleteElements(&entries_); 108 STLDeleteElements(&entries_);
109 STLDeleteElements(&staging_entries_);
108 } 110 }
109 111
110 void TabRestoreService::AddObserver(Observer* observer) { 112 void TabRestoreService::AddObserver(Observer* observer) {
111 observer_list_.AddObserver(observer); 113 observer_list_.AddObserver(observer);
112 } 114 }
113 115
114 void TabRestoreService::RemoveObserver(Observer* observer) { 116 void TabRestoreService::RemoveObserver(Observer* observer) {
115 observer_list_.RemoveObserver(observer); 117 observer_list_.RemoveObserver(observer);
116 } 118 }
117 119
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 } else { 237 } else {
236 NOTREACHED(); 238 NOTREACHED();
237 } 239 }
238 } 240 }
239 delete entry; 241 delete entry;
240 restoring_ = false; 242 restoring_ = false;
241 NotifyTabsChanged(); 243 NotifyTabsChanged();
242 } 244 }
243 245
244 void TabRestoreService::LoadTabsFromLastSession() { 246 void TabRestoreService::LoadTabsFromLastSession() {
245 if (loaded_last_session_ || reached_max_) 247 if (load_state_ != NOT_LOADED || reached_max_)
246 return; 248 return;
247 249
248 loaded_last_session_ = true; 250 load_state_ = LOADING;
249 251
252 if (!profile()->restored_last_session() &&
253 !profile()->DidLastSessionExitCleanly() &&
254 profile()->GetSessionService()) {
255 // The previous session crashed and wasn't restored. Load the tabs/windows
256 // that were open at the point of crash from the session service.
257 profile()->GetSessionService()->GetLastSession(
258 &load_consumer_,
259 NewCallback(this, &TabRestoreService::OnGotPreviousSession));
260 } else {
261 load_state_ |= LOADED_LAST_SESSION;
262 }
263
264 // Request the tabs closed in the last session. If the last session crashed,
265 // this won't contain the tabs/window that were open at the point of the
266 // crash (the call to GetLastSession above requests those).
250 ScheduleGetLastSessionCommands( 267 ScheduleGetLastSessionCommands(
251 new InternalGetCommandsRequest( 268 new InternalGetCommandsRequest(
252 NewCallback(this, &TabRestoreService::OnGotLastSessionCommands)), 269 NewCallback(this, &TabRestoreService::OnGotLastSessionCommands)),
253 &load_tabs_consumer_); 270 &load_consumer_);
254 } 271 }
255 272
256 void TabRestoreService::Save() { 273 void TabRestoreService::Save() {
257 int to_write_count = std::min(entries_to_write_, 274 int to_write_count = std::min(entries_to_write_,
258 static_cast<int>(entries_.size())); 275 static_cast<int>(entries_.size()));
259 entries_to_write_ = 0; 276 entries_to_write_ = 0;
260 if (entries_written_ + to_write_count > kEntriesPerReset) { 277 if (entries_written_ + to_write_count > kEntriesPerReset) {
261 to_write_count = entries_.size(); 278 to_write_count = entries_.size();
262 set_pending_reset(true); 279 set_pending_reset(true);
263 } 280 }
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 !ShouldTrackEntry(navigations[selected_index])) { 476 !ShouldTrackEntry(navigations[selected_index])) {
460 selected_index++; 477 selected_index++;
461 } 478 }
462 479
463 return (selected_index == max_index) ? -1 : selected_index; 480 return (selected_index == max_index) ? -1 : selected_index;
464 } 481 }
465 482
466 void TabRestoreService::OnGotLastSessionCommands( 483 void TabRestoreService::OnGotLastSessionCommands(
467 Handle handle, 484 Handle handle,
468 scoped_refptr<InternalGetCommandsRequest> request) { 485 scoped_refptr<InternalGetCommandsRequest> request) {
486 std::vector<Entry*> entries;
487 CreateEntriesFromCommands(request, &entries);
488 // Closed tabs always go to the end.
489 staging_entries_.insert(staging_entries_.end(), entries.begin(),
490 entries.end());
491 load_state_ |= LOADED_LAST_TABS;
492 LoadStateChanged();
493 }
494
495 void TabRestoreService::CreateEntriesFromCommands(
496 scoped_refptr<InternalGetCommandsRequest> request,
497 std::vector<Entry*>* loaded_entries) {
469 if (request->canceled() || entries_.size() == kMaxEntries) 498 if (request->canceled() || entries_.size() == kMaxEntries)
470 return; 499 return;
471 500
472 std::vector<SessionCommand*>& commands = request->commands; 501 std::vector<SessionCommand*>& commands = request->commands;
473 // Iterate through the commands populating entries and id_to_entry. 502 // Iterate through the commands populating entries and id_to_entry.
474 ScopedVector<Entry> entries; 503 ScopedVector<Entry> entries;
475 IDToEntry id_to_entry; 504 IDToEntry id_to_entry;
476 // If non-null we're processing the navigations of this tab. 505 // If non-null we're processing the navigations of this tab.
477 Tab* current_tab = NULL; 506 Tab* current_tab = NULL;
478 // If non-null we're processing the tabs of this window. 507 // If non-null we're processing the tabs of this window.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 default: 597 default:
569 // Unknown type, usually indicates corruption of file. Ignore it. 598 // Unknown type, usually indicates corruption of file. Ignore it.
570 return; 599 return;
571 } 600 }
572 } 601 }
573 602
574 // If there was corruption some of the entries won't be valid. Prune any 603 // If there was corruption some of the entries won't be valid. Prune any
575 // entries with no navigations. 604 // entries with no navigations.
576 ValidateAndDeleteEmptyEntries(&(entries.get())); 605 ValidateAndDeleteEmptyEntries(&(entries.get()));
577 606
578 if (entries->empty()) 607 loaded_entries->swap(entries.get());
579 return;
580
581 // And add them.
582 for (size_t i = 0; i < entries->size(); ++i)
583 AddEntry(entries[i], false, false);
584
585 // AddEntry takes ownership of the entry, need to clear out entries so that
586 // it doesn't delete them.
587 entries->clear();
588
589 // Make it so we rewrite all the tabs. We need to do this otherwise we won't
590 // correctly write out the entries when Save is invoked (Save starts from
591 // the front, not the end and we just added the entries to the end).
592 entries_to_write_ = entries_.size();
593
594 PruneAndNotify();
595 } 608 }
596 609
597 bool TabRestoreService::ValidateTab(Tab* tab) { 610 bool TabRestoreService::ValidateTab(Tab* tab) {
598 if (tab->navigations.empty()) 611 if (tab->navigations.empty())
599 return false; 612 return false;
600 613
601 tab->current_navigation_index = 614 tab->current_navigation_index =
602 std::max(0, std::min(tab->current_navigation_index, 615 std::max(0, std::min(tab->current_navigation_index,
603 static_cast<int>(tab->navigations.size()) - 1)); 616 static_cast<int>(tab->navigations.size()) - 1));
604 return true; 617 return true;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 valid_entries.push_back(*i); 653 valid_entries.push_back(*i);
641 else 654 else
642 invalid_entries.push_back(*i); 655 invalid_entries.push_back(*i);
643 } 656 }
644 // NOTE: at this point the entries are ordered with newest at the front. 657 // NOTE: at this point the entries are ordered with newest at the front.
645 entries->swap(valid_entries); 658 entries->swap(valid_entries);
646 659
647 // Delete the remaining entries. 660 // Delete the remaining entries.
648 STLDeleteElements(&invalid_entries); 661 STLDeleteElements(&invalid_entries);
649 } 662 }
663
664 void TabRestoreService::OnGotPreviousSession(
665 Handle handle,
666 std::vector<SessionWindow*>* windows) {
667 std::vector<Entry*> entries;
668 CreateEntriesFromWindows(windows, &entries);
669 // Previous session tabs go first.
670 staging_entries_.insert(staging_entries_.begin(), entries.begin(),
671 entries.end());
672 load_state_ |= LOADED_LAST_SESSION;
673 LoadStateChanged();
674 }
675
676 void TabRestoreService::CreateEntriesFromWindows(
677 std::vector<SessionWindow*>* windows,
678 std::vector<Entry*>* entries) {
679 for (size_t i = 0; i < windows->size(); ++i) {
680 scoped_ptr<Window> window(new Window());
681 if (ConvertSessionWindowToWindow((*windows)[i], window.get()))
682 entries->push_back(window.release());
683 }
684 }
685
686 bool TabRestoreService::ConvertSessionWindowToWindow(
687 SessionWindow* session_window,
688 Window* window) {
689 for (size_t i = 0; i < session_window->tabs.size(); ++i) {
690 if (!session_window->tabs[i]->navigations.empty()) {
691 window->tabs.resize(window->tabs.size() + 1);
692 Tab& tab = window->tabs.back();
693 tab.navigations.swap(session_window->tabs[i]->navigations);
694 tab.current_navigation_index =
695 session_window->tabs[i]->current_navigation_index;
696 }
697 }
698 if (window->tabs.empty())
699 return false;
700
701 window->selected_tab_index =
702 std::min(session_window->selected_tab_index,
703 static_cast<int>(window->tabs.size() - 1));
704 return true;
705 }
706
707 void TabRestoreService::LoadStateChanged() {
708 if ((load_state_ & (LOADED_LAST_TABS | LOADED_LAST_SESSION)) !=
709 (LOADED_LAST_TABS | LOADED_LAST_SESSION)) {
710 // Still waiting on previous session or previous tabs.
711 return;
712 }
713
714 // We're done loading.
715 load_state_ ^= LOADING;
716
717 if (staging_entries_.empty() || reached_max_) {
718 STLDeleteElements(&staging_entries_);
719 return;
720 }
721
722 if (staging_entries_.size() + entries_.size() > kMaxEntries) {
723 // If we add all the staged entries we'll end up with more than
724 // kMaxEntries. Delete entries such that we only end up with
725 // at most kMaxEntries.
726 DCHECK(entries_.size() < kMaxEntries);
727 STLDeleteContainerPointers(
728 staging_entries_.begin() + (kMaxEntries - entries_.size()),
729 staging_entries_.end());
730 staging_entries_.erase(
731 staging_entries_.begin() + (kMaxEntries - entries_.size()),
732 staging_entries_.end());
733 }
734
735 // And add them.
736 for (size_t i = 0; i < staging_entries_.size(); ++i)
737 AddEntry(staging_entries_[i], false, false);
738
739 // AddEntry takes ownership of the entry, need to clear out entries so that
740 // it doesn't delete them.
741 staging_entries_.clear();
742
743 // Make it so we rewrite all the tabs. We need to do this otherwise we won't
744 // correctly write out the entries when Save is invoked (Save starts from
745 // the front, not the end and we just added the entries to the end).
746 entries_to_write_ = staging_entries_.size();
747
748 PruneAndNotify();
749 }
OLDNEW
« no previous file with comments | « chrome/browser/sessions/tab_restore_service.h ('k') | chrome/browser/sessions/tab_restore_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698