| 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/files/file_path.h" | 13 #include "base/files/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/task/cancelable_task_tracker.h" | 18 #include "base/task/cancelable_task_tracker.h" |
| 19 #include "base/time/time.h" | 19 #include "base/time/time.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/base_session_service_commands.h" | 22 #include "chrome/browser/sessions/base_session_service_commands.h" |
| 23 #include "chrome/browser/sessions/base_session_service_delegate_impl.h" | 23 #include "chrome/browser/sessions/base_session_service_delegate_impl.h" |
| 24 #include "chrome/browser/sessions/session_command.h" | 24 #include "chrome/browser/sessions/session_command.h" |
| 25 #include "chrome/browser/sessions/session_service.h" | |
| 26 #include "chrome/browser/sessions/session_service_factory.h" | 25 #include "chrome/browser/sessions/session_service_factory.h" |
| 27 #include "chrome/browser/sessions/tab_restore_service_factory.h" | 26 #include "chrome/browser/sessions/tab_restore_service_factory.h" |
| 28 #include "content/public/browser/session_storage_namespace.h" | 27 #include "content/public/browser/session_storage_namespace.h" |
| 29 | 28 |
| 30 namespace { | 29 namespace { |
| 31 | 30 |
| 32 // Only written if the tab is pinned. | 31 // Only written if the tab is pinned. |
| 33 typedef bool PinnedStatePayload; | 32 typedef bool PinnedStatePayload; |
| 34 | 33 |
| 35 typedef int32 RestoredEntryPayload; | 34 typedef int32 RestoredEntryPayload; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 // Number of entries (not commands) before we clobber the file and write | 106 // Number of entries (not commands) before we clobber the file and write |
| 108 // everything. | 107 // everything. |
| 109 const int kEntriesPerReset = 40; | 108 const int kEntriesPerReset = 40; |
| 110 | 109 |
| 111 const size_t kMaxEntries = TabRestoreServiceHelper::kMaxEntries; | 110 const size_t kMaxEntries = TabRestoreServiceHelper::kMaxEntries; |
| 112 | 111 |
| 113 } // namespace | 112 } // namespace |
| 114 | 113 |
| 115 // PersistentTabRestoreService::Delegate --------------------------------------- | 114 // PersistentTabRestoreService::Delegate --------------------------------------- |
| 116 | 115 |
| 117 // Implements the link between the tab restore service and the session backend. | 116 // This restore service will create and own a BaseSessionService and implement |
| 117 // the required BaseSessionServiceDelegateImpl. |
| 118 class PersistentTabRestoreService::Delegate | 118 class PersistentTabRestoreService::Delegate |
| 119 : public BaseSessionService, | 119 : public BaseSessionServiceDelegateImpl, |
| 120 public TabRestoreServiceHelper::Observer { | 120 public TabRestoreServiceHelper::Observer { |
| 121 public: | 121 public: |
| 122 explicit Delegate(Profile* profile); | 122 explicit Delegate(Profile* profile); |
| 123 | 123 |
| 124 ~Delegate() override; | 124 ~Delegate() override; |
| 125 | 125 |
| 126 // BaseSessionService: | 126 // BaseSessionServiceDelegateImpl: |
| 127 void Save() override; | 127 void OnWillSaveCommands() override; |
| 128 | 128 |
| 129 // TabRestoreServiceHelper::Observer: | 129 // TabRestoreServiceHelper::Observer: |
| 130 void OnClearEntries() override; | 130 void OnClearEntries() override; |
| 131 void OnRestoreEntryById(SessionID::id_type id, | 131 void OnRestoreEntryById(SessionID::id_type id, |
| 132 Entries::const_iterator entry_iterator) override; | 132 Entries::const_iterator entry_iterator) override; |
| 133 void OnAddEntry() override; | 133 void OnAddEntry() override; |
| 134 | 134 |
| 135 void set_tab_restore_service_helper( | 135 void set_tab_restore_service_helper( |
| 136 TabRestoreServiceHelper* tab_restore_service_helper) { | 136 TabRestoreServiceHelper* tab_restore_service_helper) { |
| 137 tab_restore_service_helper_ = tab_restore_service_helper; | 137 tab_restore_service_helper_ = tab_restore_service_helper; |
| 138 } | 138 } |
| 139 | 139 |
| 140 void LoadTabsFromLastSession(); | 140 void LoadTabsFromLastSession(); |
| 141 | 141 |
| 142 void DeleteLastSession(); |
| 143 |
| 142 bool IsLoaded() const; | 144 bool IsLoaded() const; |
| 143 | 145 |
| 144 // Creates and add entries to |entries| for each of the windows in |windows|. | 146 // Creates and add entries to |entries| for each of the windows in |windows|. |
| 145 static void CreateEntriesFromWindows(std::vector<SessionWindow*>* windows, | 147 static void CreateEntriesFromWindows(std::vector<SessionWindow*>* windows, |
| 146 std::vector<Entry*>* entries); | 148 std::vector<Entry*>* entries); |
| 147 | 149 |
| 148 void Shutdown(); | 150 void Shutdown(); |
| 149 | 151 |
| 150 // Schedules the commands for a window close. | 152 // Schedules the commands for a window close. |
| 151 void ScheduleCommandsForWindow(const Window& window); | 153 void ScheduleCommandsForWindow(const Window& window); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 182 void OnGotLastSessionCommands(ScopedVector<SessionCommand> commands); | 184 void OnGotLastSessionCommands(ScopedVector<SessionCommand> commands); |
| 183 | 185 |
| 184 // Populates |loaded_entries| with Entries from |commands|. | 186 // Populates |loaded_entries| with Entries from |commands|. |
| 185 void CreateEntriesFromCommands(const std::vector<SessionCommand*>& commands, | 187 void CreateEntriesFromCommands(const std::vector<SessionCommand*>& commands, |
| 186 std::vector<Entry*>* loaded_entries); | 188 std::vector<Entry*>* loaded_entries); |
| 187 | 189 |
| 188 // Validates all entries in |entries|, deleting any with no navigations. This | 190 // Validates all entries in |entries|, deleting any with no navigations. This |
| 189 // also deletes any entries beyond the max number of entries we can hold. | 191 // also deletes any entries beyond the max number of entries we can hold. |
| 190 static void ValidateAndDeleteEmptyEntries(std::vector<Entry*>* entries); | 192 static void ValidateAndDeleteEmptyEntries(std::vector<Entry*>* entries); |
| 191 | 193 |
| 192 // Callback from SessionService when we've received the windows from the | 194 // Callback from BaseSessionService when we've received the windows from the |
| 193 // previous session. This creates and add entries to |staging_entries_| and | 195 // previous session. This creates and add entries to |staging_entries_| and |
| 194 // invokes LoadStateChanged. |ignored_active_window| is ignored because we | 196 // invokes LoadStateChanged. |ignored_active_window| is ignored because we |
| 195 // don't need to restore activation. | 197 // don't need to restore activation. |
| 196 void OnGotPreviousSession(ScopedVector<SessionWindow> windows, | 198 void OnGotPreviousSession(ScopedVector<SessionWindow> windows, |
| 197 SessionID::id_type ignored_active_window); | 199 SessionID::id_type ignored_active_window); |
| 198 | 200 |
| 199 // Converts a SessionWindow into a Window, returning true on success. We use 0 | 201 // Converts a SessionWindow into a Window, returning true on success. We use 0 |
| 200 // as the timestamp here since we do not know when the window/tab was closed. | 202 // as the timestamp here since we do not know when the window/tab was closed. |
| 201 static bool ConvertSessionWindowToWindow(SessionWindow* session_window, | 203 static bool ConvertSessionWindowToWindow(SessionWindow* session_window, |
| 202 Window* window); | 204 Window* window); |
| 203 | 205 |
| 204 // Invoked when previous tabs or session is loaded. If both have finished | 206 // Invoked when previous tabs or session is loaded. If both have finished |
| 205 // loading the entries in |staging_entries_| are added to entries and | 207 // loading the entries in |staging_entries_| are added to entries and |
| 206 // observers are notified. | 208 // observers are notified. |
| 207 void LoadStateChanged(); | 209 void LoadStateChanged(); |
| 208 | 210 |
| 209 // If |id_to_entry| contains an entry for |id| the corresponding entry is | 211 // If |id_to_entry| contains an entry for |id| the corresponding entry is |
| 210 // deleted and removed from both |id_to_entry| and |entries|. This is used | 212 // deleted and removed from both |id_to_entry| and |entries|. This is used |
| 211 // when creating entries from the backend file. | 213 // when creating entries from the backend file. |
| 212 void RemoveEntryByID(SessionID::id_type id, | 214 void RemoveEntryByID(SessionID::id_type id, |
| 213 IDToEntry* id_to_entry, | 215 IDToEntry* id_to_entry, |
| 214 std::vector<TabRestoreService::Entry*>* entries); | 216 std::vector<TabRestoreService::Entry*>* entries); |
| 215 | 217 |
| 216 private: | 218 private: |
| 219 scoped_ptr<BaseSessionService> base_session_service_; |
| 220 |
| 217 // The associated profile. | 221 // The associated profile. |
| 218 Profile* profile_; | 222 Profile* profile_; |
| 219 | 223 |
| 220 TabRestoreServiceHelper* tab_restore_service_helper_; | 224 TabRestoreServiceHelper* tab_restore_service_helper_; |
| 221 | 225 |
| 222 // The number of entries to write. | 226 // The number of entries to write. |
| 223 int entries_to_write_; | 227 int entries_to_write_; |
| 224 | 228 |
| 225 // Number of entries we've written. | 229 // Number of entries we've written. |
| 226 int entries_written_; | 230 int entries_written_; |
| 227 | 231 |
| 228 // Whether we've loaded the last session. | 232 // Whether we've loaded the last session. |
| 229 int load_state_; | 233 int load_state_; |
| 230 | 234 |
| 231 // Results from previously closed tabs/sessions is first added here. When the | 235 // 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 | 236 // results from both us and the session restore service have finished loading |
| 233 // LoadStateChanged is invoked, which adds these entries to entries_. | 237 // LoadStateChanged is invoked, which adds these entries to entries_. |
| 234 ScopedVector<Entry> staging_entries_; | 238 ScopedVector<Entry> staging_entries_; |
| 235 | 239 |
| 236 // Used when loading previous tabs/session and open tabs/session. | 240 // Used when loading previous tabs/session and open tabs/session. |
| 237 base::CancelableTaskTracker cancelable_task_tracker_; | 241 base::CancelableTaskTracker cancelable_task_tracker_; |
| 238 | 242 |
| 239 DISALLOW_COPY_AND_ASSIGN(Delegate); | 243 DISALLOW_COPY_AND_ASSIGN(Delegate); |
| 240 }; | 244 }; |
| 241 | 245 |
| 242 PersistentTabRestoreService::Delegate::Delegate(Profile* profile) | 246 PersistentTabRestoreService::Delegate::Delegate(Profile* profile) |
| 243 : BaseSessionService( | 247 : BaseSessionServiceDelegateImpl(true), |
| 244 BaseSessionService::TAB_RESTORE, | 248 base_session_service_( |
| 245 profile->GetPath(), | 249 new BaseSessionService(BaseSessionService::TAB_RESTORE, |
| 246 scoped_ptr<BaseSessionServiceDelegate>( | 250 profile->GetPath(), |
| 247 new BaseSessionServiceDelegateImpl(true))), | 251 this)), |
| 248 profile_(profile), | 252 profile_(profile), |
| 249 tab_restore_service_helper_(NULL), | 253 tab_restore_service_helper_(NULL), |
| 250 entries_to_write_(0), | 254 entries_to_write_(0), |
| 251 entries_written_(0), | 255 entries_written_(0), |
| 252 load_state_(NOT_LOADED) { | 256 load_state_(NOT_LOADED) { |
| 253 // We should never be created when incognito. | 257 // We should never be created when incognito. |
| 254 DCHECK(!profile->IsOffTheRecord()); | 258 DCHECK(!profile->IsOffTheRecord()); |
| 255 } | 259 } |
| 256 | 260 |
| 257 PersistentTabRestoreService::Delegate::~Delegate() {} | 261 PersistentTabRestoreService::Delegate::~Delegate() {} |
| 258 | 262 |
| 259 void PersistentTabRestoreService::Delegate::Save() { | 263 void PersistentTabRestoreService::Delegate::OnWillSaveCommands() { |
| 260 const Entries& entries = tab_restore_service_helper_->entries(); | 264 const Entries& entries = tab_restore_service_helper_->entries(); |
| 261 int to_write_count = std::min(entries_to_write_, | 265 int to_write_count = std::min(entries_to_write_, |
| 262 static_cast<int>(entries.size())); | 266 static_cast<int>(entries.size())); |
| 263 entries_to_write_ = 0; | 267 entries_to_write_ = 0; |
| 264 if (entries_written_ + to_write_count > kEntriesPerReset) { | 268 if (entries_written_ + to_write_count > kEntriesPerReset) { |
| 265 to_write_count = entries.size(); | 269 to_write_count = entries.size(); |
| 266 set_pending_reset(true); | 270 base_session_service_->set_pending_reset(true); |
| 267 } | 271 } |
| 268 if (to_write_count) { | 272 if (to_write_count) { |
| 269 // Write the to_write_count most recently added entries out. The most | 273 // Write the to_write_count most recently added entries out. The most |
| 270 // recently added entry is at the front, so we use a reverse iterator to | 274 // recently added entry is at the front, so we use a reverse iterator to |
| 271 // write in the order the entries were added. | 275 // write in the order the entries were added. |
| 272 Entries::const_reverse_iterator i = entries.rbegin(); | 276 Entries::const_reverse_iterator i = entries.rbegin(); |
| 273 DCHECK(static_cast<size_t>(to_write_count) <= entries.size()); | 277 DCHECK(static_cast<size_t>(to_write_count) <= entries.size()); |
| 274 std::advance(i, entries.size() - static_cast<int>(to_write_count)); | 278 std::advance(i, entries.size() - static_cast<int>(to_write_count)); |
| 275 for (; i != entries.rend(); ++i) { | 279 for (; i != entries.rend(); ++i) { |
| 276 Entry* entry = *i; | 280 Entry* entry = *i; |
| 277 if (entry->type == TAB) { | 281 if (entry->type == TAB) { |
| 278 Tab* tab = static_cast<Tab*>(entry); | 282 Tab* tab = static_cast<Tab*>(entry); |
| 279 int selected_index = GetSelectedNavigationIndexToPersist(*tab); | 283 int selected_index = GetSelectedNavigationIndexToPersist(*tab); |
| 280 if (selected_index != -1) | 284 if (selected_index != -1) |
| 281 ScheduleCommandsForTab(*tab, selected_index); | 285 ScheduleCommandsForTab(*tab, selected_index); |
| 282 } else { | 286 } else { |
| 283 ScheduleCommandsForWindow(*static_cast<Window*>(entry)); | 287 ScheduleCommandsForWindow(*static_cast<Window*>(entry)); |
| 284 } | 288 } |
| 285 entries_written_++; | 289 entries_written_++; |
| 286 } | 290 } |
| 287 } | 291 } |
| 288 if (pending_reset()) | 292 if (base_session_service_->pending_reset()) |
| 289 entries_written_ = 0; | 293 entries_written_ = 0; |
| 290 BaseSessionService::Save(); | |
| 291 } | 294 } |
| 292 | 295 |
| 293 void PersistentTabRestoreService::Delegate::OnClearEntries() { | 296 void PersistentTabRestoreService::Delegate::OnClearEntries() { |
| 294 // Mark all the tabs as closed so that we don't attempt to restore them. | 297 // Mark all the tabs as closed so that we don't attempt to restore them. |
| 295 const Entries& entries = tab_restore_service_helper_->entries(); | 298 const Entries& entries = tab_restore_service_helper_->entries(); |
| 296 for (Entries::const_iterator i = entries.begin(); i != entries.end(); ++i) | 299 for (Entries::const_iterator i = entries.begin(); i != entries.end(); ++i) |
| 297 ScheduleCommand(CreateRestoredEntryCommand((*i)->id).Pass()); | 300 base_session_service_->ScheduleCommand( |
| 301 CreateRestoredEntryCommand((*i)->id).Pass()); |
| 298 | 302 |
| 299 entries_to_write_ = 0; | 303 entries_to_write_ = 0; |
| 300 | 304 |
| 301 // Schedule a pending reset so that we nuke the file on next write. | 305 // Schedule a pending reset so that we nuke the file on next write. |
| 302 set_pending_reset(true); | 306 base_session_service_->set_pending_reset(true); |
| 303 | 307 |
| 304 // Schedule a command, otherwise if there are no pending commands Save does | 308 // Schedule a command, otherwise if there are no pending commands Save does |
| 305 // nothing. | 309 // nothing. |
| 306 ScheduleCommand(CreateRestoredEntryCommand(1).Pass()); | 310 base_session_service_->ScheduleCommand(CreateRestoredEntryCommand(1).Pass()); |
| 307 } | 311 } |
| 308 | 312 |
| 309 void PersistentTabRestoreService::Delegate::OnRestoreEntryById( | 313 void PersistentTabRestoreService::Delegate::OnRestoreEntryById( |
| 310 SessionID::id_type id, | 314 SessionID::id_type id, |
| 311 Entries::const_iterator entry_iterator) { | 315 Entries::const_iterator entry_iterator) { |
| 312 size_t index = 0; | 316 size_t index = 0; |
| 313 const Entries& entries = tab_restore_service_helper_->entries(); | 317 const Entries& entries = tab_restore_service_helper_->entries(); |
| 314 for (Entries::const_iterator j = entries.begin(); | 318 for (Entries::const_iterator j = entries.begin(); |
| 315 j != entry_iterator && j != entries.end(); | 319 j != entry_iterator && j != entries.end(); |
| 316 ++j, ++index) {} | 320 ++j, ++index) {} |
| 317 if (static_cast<int>(index) < entries_to_write_) | 321 if (static_cast<int>(index) < entries_to_write_) |
| 318 entries_to_write_--; | 322 entries_to_write_--; |
| 319 | 323 |
| 320 ScheduleCommand(CreateRestoredEntryCommand(id).Pass()); | 324 base_session_service_->ScheduleCommand(CreateRestoredEntryCommand(id).Pass()); |
| 321 } | 325 } |
| 322 | 326 |
| 323 void PersistentTabRestoreService::Delegate::OnAddEntry() { | 327 void PersistentTabRestoreService::Delegate::OnAddEntry() { |
| 324 // Start the save timer, when it fires we'll generate the commands. | 328 // Start the save timer, when it fires we'll generate the commands. |
| 325 StartSaveTimer(); | 329 base_session_service_->StartSaveTimer(); |
| 326 entries_to_write_++; | 330 entries_to_write_++; |
| 327 } | 331 } |
| 328 | 332 |
| 329 void PersistentTabRestoreService::Delegate::LoadTabsFromLastSession() { | 333 void PersistentTabRestoreService::Delegate::LoadTabsFromLastSession() { |
| 330 if (load_state_ != NOT_LOADED) | 334 if (load_state_ != NOT_LOADED) |
| 331 return; | 335 return; |
| 332 | 336 |
| 333 if (tab_restore_service_helper_->entries().size() == kMaxEntries) { | 337 if (tab_restore_service_helper_->entries().size() == kMaxEntries) { |
| 334 // We already have the max number of entries we can take. There is no point | 338 // We already have the max number of entries we can take. There is no point |
| 335 // in attempting to load since we'll just drop the results. Skip to loaded. | 339 // in attempting to load since we'll just drop the results. Skip to loaded. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 359 base::Bind(&Delegate::OnGotPreviousSession, base::Unretained(this)), | 363 base::Bind(&Delegate::OnGotPreviousSession, base::Unretained(this)), |
| 360 &cancelable_task_tracker_); | 364 &cancelable_task_tracker_); |
| 361 } else { | 365 } else { |
| 362 load_state_ |= LOADED_LAST_SESSION; | 366 load_state_ |= LOADED_LAST_SESSION; |
| 363 } | 367 } |
| 364 #endif | 368 #endif |
| 365 | 369 |
| 366 // Request the tabs closed in the last session. If the last session crashed, | 370 // Request the tabs closed in the last session. If the last session crashed, |
| 367 // this won't contain the tabs/window that were open at the point of the | 371 // this won't contain the tabs/window that were open at the point of the |
| 368 // crash (the call to GetLastSession above requests those). | 372 // crash (the call to GetLastSession above requests those). |
| 369 ScheduleGetLastSessionCommands( | 373 base_session_service_->ScheduleGetLastSessionCommands( |
| 370 base::Bind(&Delegate::OnGotLastSessionCommands, base::Unretained(this)), | 374 base::Bind(&Delegate::OnGotLastSessionCommands, base::Unretained(this)), |
| 371 &cancelable_task_tracker_); | 375 &cancelable_task_tracker_); |
| 372 } | 376 } |
| 373 | 377 |
| 378 void PersistentTabRestoreService::Delegate::DeleteLastSession() { |
| 379 base_session_service_->DeleteLastSession(); |
| 380 } |
| 381 |
| 374 bool PersistentTabRestoreService::Delegate::IsLoaded() const { | 382 bool PersistentTabRestoreService::Delegate::IsLoaded() const { |
| 375 return !(load_state_ & (NOT_LOADED | LOADING)); | 383 return !(load_state_ & (NOT_LOADED | LOADING)); |
| 376 } | 384 } |
| 377 | 385 |
| 378 // static | 386 // static |
| 379 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( | 387 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( |
| 380 std::vector<SessionWindow*>* windows, | 388 std::vector<SessionWindow*>* windows, |
| 381 std::vector<Entry*>* entries) { | 389 std::vector<Entry*>* entries) { |
| 382 for (size_t i = 0; i < windows->size(); ++i) { | 390 for (size_t i = 0; i < windows->size(); ++i) { |
| 383 scoped_ptr<Window> window(new Window()); | 391 scoped_ptr<Window> window(new Window()); |
| 384 if (ConvertSessionWindowToWindow((*windows)[i], window.get())) | 392 if (ConvertSessionWindowToWindow((*windows)[i], window.get())) |
| 385 entries->push_back(window.release()); | 393 entries->push_back(window.release()); |
| 386 } | 394 } |
| 387 } | 395 } |
| 388 | 396 |
| 389 void PersistentTabRestoreService::Delegate::Shutdown() { | 397 void PersistentTabRestoreService::Delegate::Shutdown() { |
| 390 if (backend()) | 398 base_session_service_->SaveNow(); |
| 391 Save(); | |
| 392 } | 399 } |
| 393 | 400 |
| 394 void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( | 401 void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( |
| 395 const Window& window) { | 402 const Window& window) { |
| 396 DCHECK(!window.tabs.empty()); | 403 DCHECK(!window.tabs.empty()); |
| 397 int selected_tab = window.selected_tab_index; | 404 int selected_tab = window.selected_tab_index; |
| 398 int valid_tab_count = 0; | 405 int valid_tab_count = 0; |
| 399 int real_selected_tab = selected_tab; | 406 int real_selected_tab = selected_tab; |
| 400 for (size_t i = 0; i < window.tabs.size(); ++i) { | 407 for (size_t i = 0; i < window.tabs.size(); ++i) { |
| 401 if (GetSelectedNavigationIndexToPersist(window.tabs[i]) != -1) { | 408 if (GetSelectedNavigationIndexToPersist(window.tabs[i]) != -1) { |
| 402 valid_tab_count++; | 409 valid_tab_count++; |
| 403 } else if (static_cast<int>(i) < selected_tab) { | 410 } else if (static_cast<int>(i) < selected_tab) { |
| 404 real_selected_tab--; | 411 real_selected_tab--; |
| 405 } | 412 } |
| 406 } | 413 } |
| 407 if (valid_tab_count == 0) | 414 if (valid_tab_count == 0) |
| 408 return; // No tabs to persist. | 415 return; // No tabs to persist. |
| 409 | 416 |
| 410 ScheduleCommand( | 417 base_session_service_->ScheduleCommand( |
| 411 CreateWindowCommand(window.id, | 418 CreateWindowCommand(window.id, |
| 412 std::min(real_selected_tab, valid_tab_count - 1), | 419 std::min(real_selected_tab, valid_tab_count - 1), |
| 413 valid_tab_count, | 420 valid_tab_count, |
| 414 window.timestamp).Pass()); | 421 window.timestamp).Pass()); |
| 415 | 422 |
| 416 if (!window.app_name.empty()) { | 423 if (!window.app_name.empty()) { |
| 417 ScheduleCommand(CreateSetWindowAppNameCommand(kCommandSetWindowAppName, | 424 base_session_service_->ScheduleCommand( |
| 418 window.id, | 425 CreateSetWindowAppNameCommand(kCommandSetWindowAppName, |
| 419 window.app_name).Pass()); | 426 window.id, |
| 427 window.app_name).Pass()); |
| 420 } | 428 } |
| 421 | 429 |
| 422 for (size_t i = 0; i < window.tabs.size(); ++i) { | 430 for (size_t i = 0; i < window.tabs.size(); ++i) { |
| 423 int selected_index = GetSelectedNavigationIndexToPersist(window.tabs[i]); | 431 int selected_index = GetSelectedNavigationIndexToPersist(window.tabs[i]); |
| 424 if (selected_index != -1) | 432 if (selected_index != -1) |
| 425 ScheduleCommandsForTab(window.tabs[i], selected_index); | 433 ScheduleCommandsForTab(window.tabs[i], selected_index); |
| 426 } | 434 } |
| 427 } | 435 } |
| 428 | 436 |
| 429 void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( | 437 void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( |
| 430 const Tab& tab, | 438 const Tab& tab, |
| 431 int selected_index) { | 439 int selected_index) { |
| 432 const std::vector<sessions::SerializedNavigationEntry>& navigations = | 440 const std::vector<sessions::SerializedNavigationEntry>& navigations = |
| 433 tab.navigations; | 441 tab.navigations; |
| 434 int max_index = static_cast<int>(navigations.size()); | 442 int max_index = static_cast<int>(navigations.size()); |
| 435 | 443 |
| 436 // Determine the first navigation we'll persist. | 444 // Determine the first navigation we'll persist. |
| 437 int valid_count_before_selected = 0; | 445 int valid_count_before_selected = 0; |
| 438 int first_index_to_persist = selected_index; | 446 int first_index_to_persist = selected_index; |
| 439 for (int i = selected_index - 1; i >= 0 && | 447 for (int i = selected_index - 1; i >= 0 && |
| 440 valid_count_before_selected < max_persist_navigation_count; --i) { | 448 valid_count_before_selected < |
| 449 BaseSessionService::max_persist_navigation_count; --i) { |
| 441 if (ShouldTrackEntry(navigations[i].virtual_url())) { | 450 if (ShouldTrackEntry(navigations[i].virtual_url())) { |
| 442 first_index_to_persist = i; | 451 first_index_to_persist = i; |
| 443 valid_count_before_selected++; | 452 valid_count_before_selected++; |
| 444 } | 453 } |
| 445 } | 454 } |
| 446 | 455 |
| 447 // Write the command that identifies the selected tab. | 456 // Write the command that identifies the selected tab. |
| 448 ScheduleCommand( | 457 base_session_service_->ScheduleCommand( |
| 449 CreateSelectedNavigationInTabCommand(tab.id, | 458 CreateSelectedNavigationInTabCommand(tab.id, |
| 450 valid_count_before_selected, | 459 valid_count_before_selected, |
| 451 tab.timestamp).Pass()); | 460 tab.timestamp).Pass()); |
| 452 | 461 |
| 453 if (tab.pinned) { | 462 if (tab.pinned) { |
| 454 PinnedStatePayload payload = true; | 463 PinnedStatePayload payload = true; |
| 455 scoped_ptr<SessionCommand> command( | 464 scoped_ptr<SessionCommand> command( |
| 456 new SessionCommand(kCommandPinnedState, sizeof(payload))); | 465 new SessionCommand(kCommandPinnedState, sizeof(payload))); |
| 457 memcpy(command->contents(), &payload, sizeof(payload)); | 466 memcpy(command->contents(), &payload, sizeof(payload)); |
| 458 ScheduleCommand(command.Pass()); | 467 base_session_service_->ScheduleCommand(command.Pass()); |
| 459 } | 468 } |
| 460 | 469 |
| 461 if (!tab.extension_app_id.empty()) { | 470 if (!tab.extension_app_id.empty()) { |
| 462 ScheduleCommand(CreateSetTabExtensionAppIDCommand( | 471 base_session_service_->ScheduleCommand( |
| 463 kCommandSetExtensionAppID, | 472 CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID, |
| 464 tab.id, | 473 tab.id, |
| 465 tab.extension_app_id).Pass()); | 474 tab.extension_app_id).Pass()); |
| 466 } | 475 } |
| 467 | 476 |
| 468 if (!tab.user_agent_override.empty()) { | 477 if (!tab.user_agent_override.empty()) { |
| 469 ScheduleCommand(CreateSetTabUserAgentOverrideCommand( | 478 base_session_service_->ScheduleCommand( |
| 470 kCommandSetTabUserAgentOverride, | 479 CreateSetTabUserAgentOverrideCommand(kCommandSetTabUserAgentOverride, |
| 471 tab.id, | 480 tab.id, |
| 472 tab.user_agent_override).Pass()); | 481 tab.user_agent_override).Pass()); |
| 473 } | 482 } |
| 474 | 483 |
| 475 // Then write the navigations. | 484 // Then write the navigations. |
| 476 for (int i = first_index_to_persist, wrote_count = 0; | 485 for (int i = first_index_to_persist, wrote_count = 0; |
| 477 i < max_index && wrote_count < 2 * max_persist_navigation_count; ++i) { | 486 wrote_count < 2 * BaseSessionService::max_persist_navigation_count && |
| 487 i < max_index; ++i) { |
| 478 if (ShouldTrackEntry(navigations[i].virtual_url())) { | 488 if (ShouldTrackEntry(navigations[i].virtual_url())) { |
| 479 ScheduleCommand(CreateUpdateTabNavigationCommand( | 489 base_session_service_->ScheduleCommand( |
| 480 kCommandUpdateTabNavigation, | 490 CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, |
| 481 tab.id, | 491 tab.id, |
| 482 navigations[i])); | 492 navigations[i])); |
| 483 } | 493 } |
| 484 } | 494 } |
| 485 } | 495 } |
| 486 | 496 |
| 487 // static | 497 // static |
| 488 scoped_ptr<SessionCommand> | 498 scoped_ptr<SessionCommand> |
| 489 PersistentTabRestoreService::Delegate::CreateWindowCommand( | 499 PersistentTabRestoreService::Delegate::CreateWindowCommand( |
| 490 SessionID::id_type id, | 500 SessionID::id_type id, |
| 491 int selected_tab_index, | 501 int selected_tab_index, |
| 492 int num_tabs, | 502 int num_tabs, |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 } | 1009 } |
| 1000 | 1010 |
| 1001 void PersistentTabRestoreService::PruneEntries() { | 1011 void PersistentTabRestoreService::PruneEntries() { |
| 1002 helper_.PruneEntries(); | 1012 helper_.PruneEntries(); |
| 1003 } | 1013 } |
| 1004 | 1014 |
| 1005 KeyedService* TabRestoreServiceFactory::BuildServiceInstanceFor( | 1015 KeyedService* TabRestoreServiceFactory::BuildServiceInstanceFor( |
| 1006 content::BrowserContext* profile) const { | 1016 content::BrowserContext* profile) const { |
| 1007 return new PersistentTabRestoreService(static_cast<Profile*>(profile), NULL); | 1017 return new PersistentTabRestoreService(static_cast<Profile*>(profile), NULL); |
| 1008 } | 1018 } |
| OLD | NEW |