| 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_delegate_impl.h" | 23 #include "chrome/browser/sessions/base_session_service_delegate_impl.h" |
| 23 #include "chrome/browser/sessions/session_command.h" | 24 #include "chrome/browser/sessions/session_command.h" |
| 24 #include "chrome/browser/sessions/session_service.h" | 25 #include "chrome/browser/sessions/session_service.h" |
| 25 #include "chrome/browser/sessions/session_service_factory.h" | 26 #include "chrome/browser/sessions/session_service_factory.h" |
| 26 #include "chrome/browser/sessions/tab_restore_service_factory.h" | 27 #include "chrome/browser/sessions/tab_restore_service_factory.h" |
| 27 #include "content/public/browser/session_storage_namespace.h" | 28 #include "content/public/browser/session_storage_namespace.h" |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 // Only written if the tab is pinned. | 32 // Only written if the tab is pinned. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 // Number of entries (not commands) before we clobber the file and write | 107 // Number of entries (not commands) before we clobber the file and write |
| 107 // everything. | 108 // everything. |
| 108 const int kEntriesPerReset = 40; | 109 const int kEntriesPerReset = 40; |
| 109 | 110 |
| 110 const size_t kMaxEntries = TabRestoreServiceHelper::kMaxEntries; | 111 const size_t kMaxEntries = TabRestoreServiceHelper::kMaxEntries; |
| 111 | 112 |
| 112 } // namespace | 113 } // namespace |
| 113 | 114 |
| 114 // PersistentTabRestoreService::Delegate --------------------------------------- | 115 // PersistentTabRestoreService::Delegate --------------------------------------- |
| 115 | 116 |
| 116 // Implements the link between the tab restore service and the session backend. | 117 // Implements the link between the tab restore service and BaseSessionService. |
| 117 class PersistentTabRestoreService::Delegate | 118 class PersistentTabRestoreService::Delegate |
| 118 : public BaseSessionService, | 119 : public BaseSessionServiceDelegateImpl, |
| 119 public TabRestoreServiceHelper::Observer { | 120 public TabRestoreServiceHelper::Observer { |
| 120 public: | 121 public: |
| 121 explicit Delegate(Profile* profile); | 122 explicit Delegate(Profile* profile); |
| 122 | 123 |
| 123 ~Delegate() override; | 124 ~Delegate() override; |
| 124 | 125 |
| 125 // BaseSessionService: | 126 // BaseSessionServiceDelegateImpl: |
| 126 void Save() override; | 127 void OnWillSaveCommands() override; |
| 128 void OnSavedCommands() override; |
| 127 | 129 |
| 128 // TabRestoreServiceHelper::Observer: | 130 // TabRestoreServiceHelper::Observer: |
| 129 void OnClearEntries() override; | 131 void OnClearEntries() override; |
| 130 void OnRestoreEntryById(SessionID::id_type id, | 132 void OnRestoreEntryById(SessionID::id_type id, |
| 131 Entries::const_iterator entry_iterator) override; | 133 Entries::const_iterator entry_iterator) override; |
| 132 void OnAddEntry() override; | 134 void OnAddEntry() override; |
| 133 | 135 |
| 134 void set_tab_restore_service_helper( | 136 void set_tab_restore_service_helper( |
| 135 TabRestoreServiceHelper* tab_restore_service_helper) { | 137 TabRestoreServiceHelper* tab_restore_service_helper) { |
| 136 tab_restore_service_helper_ = tab_restore_service_helper; | 138 tab_restore_service_helper_ = tab_restore_service_helper; |
| 137 } | 139 } |
| 138 | 140 |
| 139 void LoadTabsFromLastSession(); | 141 void LoadTabsFromLastSession(); |
| 140 | 142 |
| 143 void DeleteLastSession(); |
| 144 |
| 141 bool IsLoaded() const; | 145 bool IsLoaded() const; |
| 142 | 146 |
| 143 // Creates and add entries to |entries| for each of the windows in |windows|. | 147 // Creates and add entries to |entries| for each of the windows in |windows|. |
| 144 static void CreateEntriesFromWindows(std::vector<SessionWindow*>* windows, | 148 static void CreateEntriesFromWindows(std::vector<SessionWindow*>* windows, |
| 145 std::vector<Entry*>* entries); | 149 std::vector<Entry*>* entries); |
| 146 | 150 |
| 147 void Shutdown(); | 151 void Shutdown(); |
| 148 | 152 |
| 149 // Schedules the commands for a window close. | 153 // Schedules the commands for a window close. |
| 150 void ScheduleCommandsForWindow(const Window& window); | 154 void ScheduleCommandsForWindow(const Window& window); |
| 151 | 155 |
| 152 // Schedules the commands for a tab close. |selected_index| gives the index of | 156 // Schedules the commands for a tab close. |selected_index| gives the index of |
| 153 // the selected navigation. | 157 // the selected navigation. |
| 154 void ScheduleCommandsForTab(const Tab& tab, int selected_index); | 158 void ScheduleCommandsForTab(const Tab& tab, int selected_index); |
| 155 | 159 |
| 156 // Creates a window close command. | 160 // Creates a window close command. |
| 157 static SessionCommand* CreateWindowCommand(SessionID::id_type id, | 161 static scoped_ptr<SessionCommand> CreateWindowCommand(SessionID::id_type id, |
| 158 int selected_tab_index, | 162 int selected_tab_index, |
| 159 int num_tabs, | 163 int num_tabs, |
| 160 base::Time timestamp); | 164 base::Time timestamp); |
| 161 | 165 |
| 162 // Creates a tab close command. | 166 // Creates a tab close command. |
| 163 static SessionCommand* CreateSelectedNavigationInTabCommand( | 167 static scoped_ptr<SessionCommand> CreateSelectedNavigationInTabCommand( |
| 164 SessionID::id_type tab_id, | 168 SessionID::id_type tab_id, |
| 165 int32 index, | 169 int32 index, |
| 166 base::Time timestamp); | 170 base::Time timestamp); |
| 167 | 171 |
| 168 // Creates a restore command. | 172 // Creates a restore command. |
| 169 static SessionCommand* CreateRestoredEntryCommand( | 173 static scoped_ptr<SessionCommand> CreateRestoredEntryCommand( |
| 170 SessionID::id_type entry_id); | 174 SessionID::id_type entry_id); |
| 171 | 175 |
| 172 // Returns the index to persist as the selected index. This is the same as | 176 // Returns the index to persist as the selected index. This is the same as |
| 173 // |tab.current_navigation_index| unless the entry at | 177 // |tab.current_navigation_index| unless the entry at |
| 174 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if no | 178 // |tab.current_navigation_index| shouldn't be persisted. Returns -1 if no |
| 175 // valid navigation to persist. | 179 // valid navigation to persist. |
| 176 int GetSelectedNavigationIndexToPersist(const Tab& tab); | 180 int GetSelectedNavigationIndexToPersist(const Tab& tab); |
| 177 | 181 |
| 178 // Invoked when we've loaded the session commands that identify the previously | 182 // Invoked when we've loaded the session commands that identify the previously |
| 179 // closed tabs. This creates entries, adds them to staging_entries_, and | 183 // closed tabs. This creates entries, adds them to staging_entries_, and |
| (...skipping 26 matching lines...) Expand all Loading... |
| 206 void LoadStateChanged(); | 210 void LoadStateChanged(); |
| 207 | 211 |
| 208 // If |id_to_entry| contains an entry for |id| the corresponding entry is | 212 // If |id_to_entry| contains an entry for |id| the corresponding entry is |
| 209 // deleted and removed from both |id_to_entry| and |entries|. This is used | 213 // deleted and removed from both |id_to_entry| and |entries|. This is used |
| 210 // when creating entries from the backend file. | 214 // when creating entries from the backend file. |
| 211 void RemoveEntryByID(SessionID::id_type id, | 215 void RemoveEntryByID(SessionID::id_type id, |
| 212 IDToEntry* id_to_entry, | 216 IDToEntry* id_to_entry, |
| 213 std::vector<TabRestoreService::Entry*>* entries); | 217 std::vector<TabRestoreService::Entry*>* entries); |
| 214 | 218 |
| 215 private: | 219 private: |
| 220 scoped_ptr<BaseSessionService> base_session_service_; |
| 221 |
| 216 // The associated profile. | 222 // The associated profile. |
| 217 Profile* profile_; | 223 Profile* profile_; |
| 218 | 224 |
| 219 TabRestoreServiceHelper* tab_restore_service_helper_; | 225 TabRestoreServiceHelper* tab_restore_service_helper_; |
| 220 | 226 |
| 221 // The number of entries to write. | 227 // The number of entries to write. |
| 222 int entries_to_write_; | 228 int entries_to_write_; |
| 223 | 229 |
| 224 // Number of entries we've written. | 230 // Number of entries we've written. |
| 225 int entries_written_; | 231 int entries_written_; |
| 226 | 232 |
| 227 // Whether we've loaded the last session. | 233 // Whether we've loaded the last session. |
| 228 int load_state_; | 234 int load_state_; |
| 229 | 235 |
| 230 // Results from previously closed tabs/sessions is first added here. When the | 236 // Results from previously closed tabs/sessions is first added here. When the |
| 231 // results from both us and the session restore service have finished loading | 237 // results from both us and the session restore service have finished loading |
| 232 // LoadStateChanged is invoked, which adds these entries to entries_. | 238 // LoadStateChanged is invoked, which adds these entries to entries_. |
| 233 ScopedVector<Entry> staging_entries_; | 239 ScopedVector<Entry> staging_entries_; |
| 234 | 240 |
| 235 // Used when loading previous tabs/session and open tabs/session. | 241 // Used when loading previous tabs/session and open tabs/session. |
| 236 base::CancelableTaskTracker cancelable_task_tracker_; | 242 base::CancelableTaskTracker cancelable_task_tracker_; |
| 237 | 243 |
| 238 DISALLOW_COPY_AND_ASSIGN(Delegate); | 244 DISALLOW_COPY_AND_ASSIGN(Delegate); |
| 239 }; | 245 }; |
| 240 | 246 |
| 241 PersistentTabRestoreService::Delegate::Delegate(Profile* profile) | 247 PersistentTabRestoreService::Delegate::Delegate(Profile* profile) |
| 242 : BaseSessionService( | 248 : BaseSessionServiceDelegateImpl(true), |
| 243 BaseSessionService::TAB_RESTORE, | 249 base_session_service_( |
| 244 profile->GetPath(), | 250 new BaseSessionService(BaseSessionService::TAB_RESTORE, |
| 245 scoped_ptr<BaseSessionServiceDelegate>( | 251 profile->GetPath(), |
| 246 new BaseSessionServiceDelegateImpl(true))), | 252 this)), |
| 247 profile_(profile), | 253 profile_(profile), |
| 248 tab_restore_service_helper_(NULL), | 254 tab_restore_service_helper_(NULL), |
| 249 entries_to_write_(0), | 255 entries_to_write_(0), |
| 250 entries_written_(0), | 256 entries_written_(0), |
| 251 load_state_(NOT_LOADED) { | 257 load_state_(NOT_LOADED) { |
| 252 // We should never be created when incognito. | 258 // We should never be created when incognito. |
| 253 DCHECK(!profile->IsOffTheRecord()); | 259 DCHECK(!profile->IsOffTheRecord()); |
| 254 } | 260 } |
| 255 | 261 |
| 256 PersistentTabRestoreService::Delegate::~Delegate() {} | 262 PersistentTabRestoreService::Delegate::~Delegate() {} |
| 257 | 263 |
| 258 void PersistentTabRestoreService::Delegate::Save() { | 264 void PersistentTabRestoreService::Delegate::OnWillSaveCommands() { |
| 259 const Entries& entries = tab_restore_service_helper_->entries(); | 265 const Entries& entries = tab_restore_service_helper_->entries(); |
| 260 int to_write_count = std::min(entries_to_write_, | 266 int to_write_count = std::min(entries_to_write_, |
| 261 static_cast<int>(entries.size())); | 267 static_cast<int>(entries.size())); |
| 262 entries_to_write_ = 0; | 268 entries_to_write_ = 0; |
| 263 if (entries_written_ + to_write_count > kEntriesPerReset) { | 269 if (entries_written_ + to_write_count > kEntriesPerReset) { |
| 264 to_write_count = entries.size(); | 270 to_write_count = entries.size(); |
| 265 set_pending_reset(true); | 271 base_session_service_->set_pending_reset(true); |
| 266 } | 272 } |
| 267 if (to_write_count) { | 273 if (to_write_count) { |
| 268 // Write the to_write_count most recently added entries out. The most | 274 // Write the to_write_count most recently added entries out. The most |
| 269 // recently added entry is at the front, so we use a reverse iterator to | 275 // recently added entry is at the front, so we use a reverse iterator to |
| 270 // write in the order the entries were added. | 276 // write in the order the entries were added. |
| 271 Entries::const_reverse_iterator i = entries.rbegin(); | 277 Entries::const_reverse_iterator i = entries.rbegin(); |
| 272 DCHECK(static_cast<size_t>(to_write_count) <= entries.size()); | 278 DCHECK(static_cast<size_t>(to_write_count) <= entries.size()); |
| 273 std::advance(i, entries.size() - static_cast<int>(to_write_count)); | 279 std::advance(i, entries.size() - static_cast<int>(to_write_count)); |
| 274 for (; i != entries.rend(); ++i) { | 280 for (; i != entries.rend(); ++i) { |
| 275 Entry* entry = *i; | 281 Entry* entry = *i; |
| 276 if (entry->type == TAB) { | 282 if (entry->type == TAB) { |
| 277 Tab* tab = static_cast<Tab*>(entry); | 283 Tab* tab = static_cast<Tab*>(entry); |
| 278 int selected_index = GetSelectedNavigationIndexToPersist(*tab); | 284 int selected_index = GetSelectedNavigationIndexToPersist(*tab); |
| 279 if (selected_index != -1) | 285 if (selected_index != -1) |
| 280 ScheduleCommandsForTab(*tab, selected_index); | 286 ScheduleCommandsForTab(*tab, selected_index); |
| 281 } else { | 287 } else { |
| 282 ScheduleCommandsForWindow(*static_cast<Window*>(entry)); | 288 ScheduleCommandsForWindow(*static_cast<Window*>(entry)); |
| 283 } | 289 } |
| 284 entries_written_++; | 290 entries_written_++; |
| 285 } | 291 } |
| 286 } | 292 } |
| 287 if (pending_reset()) | 293 if (base_session_service_->pending_reset()) |
| 288 entries_written_ = 0; | 294 entries_written_ = 0; |
| 289 BaseSessionService::Save(); | |
| 290 } | 295 } |
| 291 | 296 |
| 297 void PersistentTabRestoreService::Delegate::OnSavedCommands() {} |
| 298 |
| 292 void PersistentTabRestoreService::Delegate::OnClearEntries() { | 299 void PersistentTabRestoreService::Delegate::OnClearEntries() { |
| 293 // Mark all the tabs as closed so that we don't attempt to restore them. | 300 // Mark all the tabs as closed so that we don't attempt to restore them. |
| 294 const Entries& entries = tab_restore_service_helper_->entries(); | 301 const Entries& entries = tab_restore_service_helper_->entries(); |
| 295 for (Entries::const_iterator i = entries.begin(); i != entries.end(); ++i) | 302 for (Entries::const_iterator i = entries.begin(); i != entries.end(); ++i) |
| 296 ScheduleCommand(CreateRestoredEntryCommand((*i)->id)); | 303 base_session_service_->ScheduleCommand( |
| 304 CreateRestoredEntryCommand((*i)->id).Pass()); |
| 297 | 305 |
| 298 entries_to_write_ = 0; | 306 entries_to_write_ = 0; |
| 299 | 307 |
| 300 // Schedule a pending reset so that we nuke the file on next write. | 308 // Schedule a pending reset so that we nuke the file on next write. |
| 301 set_pending_reset(true); | 309 base_session_service_->set_pending_reset(true); |
| 302 | 310 |
| 303 // Schedule a command, otherwise if there are no pending commands Save does | 311 // Schedule a command, otherwise if there are no pending commands Save does |
| 304 // nothing. | 312 // nothing. |
| 305 ScheduleCommand(CreateRestoredEntryCommand(1)); | 313 base_session_service_->ScheduleCommand(CreateRestoredEntryCommand(1).Pass()); |
| 306 } | 314 } |
| 307 | 315 |
| 308 void PersistentTabRestoreService::Delegate::OnRestoreEntryById( | 316 void PersistentTabRestoreService::Delegate::OnRestoreEntryById( |
| 309 SessionID::id_type id, | 317 SessionID::id_type id, |
| 310 Entries::const_iterator entry_iterator) { | 318 Entries::const_iterator entry_iterator) { |
| 311 size_t index = 0; | 319 size_t index = 0; |
| 312 const Entries& entries = tab_restore_service_helper_->entries(); | 320 const Entries& entries = tab_restore_service_helper_->entries(); |
| 313 for (Entries::const_iterator j = entries.begin(); | 321 for (Entries::const_iterator j = entries.begin(); |
| 314 j != entry_iterator && j != entries.end(); | 322 j != entry_iterator && j != entries.end(); |
| 315 ++j, ++index) {} | 323 ++j, ++index) {} |
| 316 if (static_cast<int>(index) < entries_to_write_) | 324 if (static_cast<int>(index) < entries_to_write_) |
| 317 entries_to_write_--; | 325 entries_to_write_--; |
| 318 | 326 |
| 319 ScheduleCommand(CreateRestoredEntryCommand(id)); | 327 base_session_service_->ScheduleCommand(CreateRestoredEntryCommand(id).Pass()); |
| 320 } | 328 } |
| 321 | 329 |
| 322 void PersistentTabRestoreService::Delegate::OnAddEntry() { | 330 void PersistentTabRestoreService::Delegate::OnAddEntry() { |
| 323 // Start the save timer, when it fires we'll generate the commands. | 331 // Start the save timer, when it fires we'll generate the commands. |
| 324 StartSaveTimer(); | 332 base_session_service_->StartSaveTimer(); |
| 325 entries_to_write_++; | 333 entries_to_write_++; |
| 326 } | 334 } |
| 327 | 335 |
| 328 void PersistentTabRestoreService::Delegate::LoadTabsFromLastSession() { | 336 void PersistentTabRestoreService::Delegate::LoadTabsFromLastSession() { |
| 329 if (load_state_ != NOT_LOADED) | 337 if (load_state_ != NOT_LOADED) |
| 330 return; | 338 return; |
| 331 | 339 |
| 332 if (tab_restore_service_helper_->entries().size() == kMaxEntries) { | 340 if (tab_restore_service_helper_->entries().size() == kMaxEntries) { |
| 333 // We already have the max number of entries we can take. There is no point | 341 // We already have the max number of entries we can take. There is no point |
| 334 // in attempting to load since we'll just drop the results. Skip to loaded. | 342 // in attempting to load since we'll just drop the results. Skip to loaded. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 358 base::Bind(&Delegate::OnGotPreviousSession, base::Unretained(this)), | 366 base::Bind(&Delegate::OnGotPreviousSession, base::Unretained(this)), |
| 359 &cancelable_task_tracker_); | 367 &cancelable_task_tracker_); |
| 360 } else { | 368 } else { |
| 361 load_state_ |= LOADED_LAST_SESSION; | 369 load_state_ |= LOADED_LAST_SESSION; |
| 362 } | 370 } |
| 363 #endif | 371 #endif |
| 364 | 372 |
| 365 // Request the tabs closed in the last session. If the last session crashed, | 373 // Request the tabs closed in the last session. If the last session crashed, |
| 366 // this won't contain the tabs/window that were open at the point of the | 374 // this won't contain the tabs/window that were open at the point of the |
| 367 // crash (the call to GetLastSession above requests those). | 375 // crash (the call to GetLastSession above requests those). |
| 368 ScheduleGetLastSessionCommands( | 376 base_session_service_->ScheduleGetLastSessionCommands( |
| 369 base::Bind(&Delegate::OnGotLastSessionCommands, base::Unretained(this)), | 377 base::Bind(&Delegate::OnGotLastSessionCommands, base::Unretained(this)), |
| 370 &cancelable_task_tracker_); | 378 &cancelable_task_tracker_); |
| 371 } | 379 } |
| 372 | 380 |
| 381 void PersistentTabRestoreService::Delegate::DeleteLastSession() { |
| 382 base_session_service_->DeleteLastSession(); |
| 383 } |
| 384 |
| 373 bool PersistentTabRestoreService::Delegate::IsLoaded() const { | 385 bool PersistentTabRestoreService::Delegate::IsLoaded() const { |
| 374 return !(load_state_ & (NOT_LOADED | LOADING)); | 386 return !(load_state_ & (NOT_LOADED | LOADING)); |
| 375 } | 387 } |
| 376 | 388 |
| 377 // static | 389 // static |
| 378 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( | 390 void PersistentTabRestoreService::Delegate::CreateEntriesFromWindows( |
| 379 std::vector<SessionWindow*>* windows, | 391 std::vector<SessionWindow*>* windows, |
| 380 std::vector<Entry*>* entries) { | 392 std::vector<Entry*>* entries) { |
| 381 for (size_t i = 0; i < windows->size(); ++i) { | 393 for (size_t i = 0; i < windows->size(); ++i) { |
| 382 scoped_ptr<Window> window(new Window()); | 394 scoped_ptr<Window> window(new Window()); |
| 383 if (ConvertSessionWindowToWindow((*windows)[i], window.get())) | 395 if (ConvertSessionWindowToWindow((*windows)[i], window.get())) |
| 384 entries->push_back(window.release()); | 396 entries->push_back(window.release()); |
| 385 } | 397 } |
| 386 } | 398 } |
| 387 | 399 |
| 388 void PersistentTabRestoreService::Delegate::Shutdown() { | 400 void PersistentTabRestoreService::Delegate::Shutdown() { |
| 389 if (backend()) | 401 base_session_service_->SaveNow(); |
| 390 Save(); | |
| 391 } | 402 } |
| 392 | 403 |
| 393 void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( | 404 void PersistentTabRestoreService::Delegate::ScheduleCommandsForWindow( |
| 394 const Window& window) { | 405 const Window& window) { |
| 395 DCHECK(!window.tabs.empty()); | 406 DCHECK(!window.tabs.empty()); |
| 396 int selected_tab = window.selected_tab_index; | 407 int selected_tab = window.selected_tab_index; |
| 397 int valid_tab_count = 0; | 408 int valid_tab_count = 0; |
| 398 int real_selected_tab = selected_tab; | 409 int real_selected_tab = selected_tab; |
| 399 for (size_t i = 0; i < window.tabs.size(); ++i) { | 410 for (size_t i = 0; i < window.tabs.size(); ++i) { |
| 400 if (GetSelectedNavigationIndexToPersist(window.tabs[i]) != -1) { | 411 if (GetSelectedNavigationIndexToPersist(window.tabs[i]) != -1) { |
| 401 valid_tab_count++; | 412 valid_tab_count++; |
| 402 } else if (static_cast<int>(i) < selected_tab) { | 413 } else if (static_cast<int>(i) < selected_tab) { |
| 403 real_selected_tab--; | 414 real_selected_tab--; |
| 404 } | 415 } |
| 405 } | 416 } |
| 406 if (valid_tab_count == 0) | 417 if (valid_tab_count == 0) |
| 407 return; // No tabs to persist. | 418 return; // No tabs to persist. |
| 408 | 419 |
| 409 ScheduleCommand( | 420 base_session_service_->ScheduleCommand( |
| 410 CreateWindowCommand(window.id, | 421 CreateWindowCommand(window.id, |
| 411 std::min(real_selected_tab, valid_tab_count - 1), | 422 std::min(real_selected_tab, valid_tab_count - 1), |
| 412 valid_tab_count, | 423 valid_tab_count, |
| 413 window.timestamp)); | 424 window.timestamp).Pass()); |
| 414 | 425 |
| 415 if (!window.app_name.empty()) { | 426 if (!window.app_name.empty()) { |
| 416 ScheduleCommand( | 427 base_session_service_->ScheduleCommand( |
| 417 CreateSetWindowAppNameCommand(kCommandSetWindowAppName, | 428 BaseSessionServiceCommands::CreateSetWindowAppNameCommand( |
| 418 window.id, | 429 kCommandSetWindowAppName, |
| 419 window.app_name)); | 430 window.id, |
| 431 window.app_name).Pass()); |
| 420 } | 432 } |
| 421 | 433 |
| 422 for (size_t i = 0; i < window.tabs.size(); ++i) { | 434 for (size_t i = 0; i < window.tabs.size(); ++i) { |
| 423 int selected_index = GetSelectedNavigationIndexToPersist(window.tabs[i]); | 435 int selected_index = GetSelectedNavigationIndexToPersist(window.tabs[i]); |
| 424 if (selected_index != -1) | 436 if (selected_index != -1) |
| 425 ScheduleCommandsForTab(window.tabs[i], selected_index); | 437 ScheduleCommandsForTab(window.tabs[i], selected_index); |
| 426 } | 438 } |
| 427 } | 439 } |
| 428 | 440 |
| 429 void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( | 441 void PersistentTabRestoreService::Delegate::ScheduleCommandsForTab( |
| 430 const Tab& tab, | 442 const Tab& tab, |
| 431 int selected_index) { | 443 int selected_index) { |
| 432 const std::vector<sessions::SerializedNavigationEntry>& navigations = | 444 const std::vector<sessions::SerializedNavigationEntry>& navigations = |
| 433 tab.navigations; | 445 tab.navigations; |
| 434 int max_index = static_cast<int>(navigations.size()); | 446 int max_index = static_cast<int>(navigations.size()); |
| 435 | 447 |
| 436 // Determine the first navigation we'll persist. | 448 // Determine the first navigation we'll persist. |
| 437 int valid_count_before_selected = 0; | 449 int valid_count_before_selected = 0; |
| 438 int first_index_to_persist = selected_index; | 450 int first_index_to_persist = selected_index; |
| 439 for (int i = selected_index - 1; i >= 0 && | 451 for (int i = selected_index - 1; i >= 0 && |
| 440 valid_count_before_selected < max_persist_navigation_count; --i) { | 452 valid_count_before_selected < |
| 453 BaseSessionService::max_persist_navigation_count; --i) { |
| 441 if (ShouldTrackEntry(navigations[i].virtual_url())) { | 454 if (ShouldTrackEntry(navigations[i].virtual_url())) { |
| 442 first_index_to_persist = i; | 455 first_index_to_persist = i; |
| 443 valid_count_before_selected++; | 456 valid_count_before_selected++; |
| 444 } | 457 } |
| 445 } | 458 } |
| 446 | 459 |
| 447 // Write the command that identifies the selected tab. | 460 // Write the command that identifies the selected tab. |
| 448 ScheduleCommand( | 461 base_session_service_->ScheduleCommand( |
| 449 CreateSelectedNavigationInTabCommand(tab.id, | 462 CreateSelectedNavigationInTabCommand(tab.id, |
| 450 valid_count_before_selected, | 463 valid_count_before_selected, |
| 451 tab.timestamp)); | 464 tab.timestamp).Pass()); |
| 452 | 465 |
| 453 if (tab.pinned) { | 466 if (tab.pinned) { |
| 454 PinnedStatePayload payload = true; | 467 PinnedStatePayload payload = true; |
| 455 SessionCommand* command = | 468 scoped_ptr<SessionCommand> command( |
| 456 new SessionCommand(kCommandPinnedState, sizeof(payload)); | 469 new SessionCommand(kCommandPinnedState, sizeof(payload))); |
| 457 memcpy(command->contents(), &payload, sizeof(payload)); | 470 memcpy(command->contents(), &payload, sizeof(payload)); |
| 458 ScheduleCommand(command); | 471 base_session_service_->ScheduleCommand(command.Pass()); |
| 459 } | 472 } |
| 460 | 473 |
| 461 if (!tab.extension_app_id.empty()) { | 474 if (!tab.extension_app_id.empty()) { |
| 462 ScheduleCommand( | 475 base_session_service_->ScheduleCommand( |
| 463 CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID, tab.id, | 476 BaseSessionServiceCommands::CreateSetTabExtensionAppIDCommand( |
| 464 tab.extension_app_id)); | 477 kCommandSetExtensionAppID, |
| 478 tab.id, |
| 479 tab.extension_app_id).Pass()); |
| 465 } | 480 } |
| 466 | 481 |
| 467 if (!tab.user_agent_override.empty()) { | 482 if (!tab.user_agent_override.empty()) { |
| 468 ScheduleCommand( | 483 base_session_service_->ScheduleCommand( |
| 469 CreateSetTabUserAgentOverrideCommand(kCommandSetTabUserAgentOverride, | 484 BaseSessionServiceCommands::CreateSetTabUserAgentOverrideCommand( |
| 470 tab.id, tab.user_agent_override)); | 485 kCommandSetTabUserAgentOverride, |
| 486 tab.id, |
| 487 tab.user_agent_override).Pass()); |
| 471 } | 488 } |
| 472 | 489 |
| 473 // Then write the navigations. | 490 // Then write the navigations. |
| 474 for (int i = first_index_to_persist, wrote_count = 0; | 491 for (int i = first_index_to_persist, wrote_count = 0; |
| 475 i < max_index && wrote_count < 2 * max_persist_navigation_count; ++i) { | 492 wrote_count < 2 * BaseSessionService::max_persist_navigation_count && |
| 493 i < max_index; ++i) { |
| 476 if (ShouldTrackEntry(navigations[i].virtual_url())) { | 494 if (ShouldTrackEntry(navigations[i].virtual_url())) { |
| 477 ScheduleCommand( | 495 base_session_service_->ScheduleCommand( |
| 478 CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, tab.id, | 496 BaseSessionServiceCommands::CreateUpdateTabNavigationCommand( |
| 479 navigations[i])); | 497 kCommandUpdateTabNavigation, |
| 498 tab.id, |
| 499 navigations[i])); |
| 480 } | 500 } |
| 481 } | 501 } |
| 482 } | 502 } |
| 483 | 503 |
| 484 // static | 504 // static |
| 485 SessionCommand* PersistentTabRestoreService::Delegate::CreateWindowCommand( | 505 scoped_ptr<SessionCommand> |
| 506 PersistentTabRestoreService::Delegate::CreateWindowCommand( |
| 486 SessionID::id_type id, | 507 SessionID::id_type id, |
| 487 int selected_tab_index, | 508 int selected_tab_index, |
| 488 int num_tabs, | 509 int num_tabs, |
| 489 base::Time timestamp) { | 510 base::Time timestamp) { |
| 490 WindowPayload2 payload; | 511 WindowPayload2 payload; |
| 491 // |timestamp| is aligned on a 16 byte boundary, leaving 4 bytes of | 512 // |timestamp| is aligned on a 16 byte boundary, leaving 4 bytes of |
| 492 // uninitialized memory in the struct. | 513 // uninitialized memory in the struct. |
| 493 memset(&payload, 0, sizeof(payload)); | 514 memset(&payload, 0, sizeof(payload)); |
| 494 payload.window_id = id; | 515 payload.window_id = id; |
| 495 payload.selected_tab_index = selected_tab_index; | 516 payload.selected_tab_index = selected_tab_index; |
| 496 payload.num_tabs = num_tabs; | 517 payload.num_tabs = num_tabs; |
| 497 payload.timestamp = timestamp.ToInternalValue(); | 518 payload.timestamp = timestamp.ToInternalValue(); |
| 498 | 519 |
| 499 SessionCommand* command = | 520 scoped_ptr<SessionCommand> command( |
| 500 new SessionCommand(kCommandWindow, sizeof(payload)); | 521 new SessionCommand(kCommandWindow, sizeof(payload))); |
| 501 memcpy(command->contents(), &payload, sizeof(payload)); | 522 memcpy(command->contents(), &payload, sizeof(payload)); |
| 502 return command; | 523 return command.Pass(); |
| 503 } | 524 } |
| 504 | 525 |
| 505 // static | 526 // static |
| 506 SessionCommand* | 527 scoped_ptr<SessionCommand> |
| 507 PersistentTabRestoreService::Delegate::CreateSelectedNavigationInTabCommand( | 528 PersistentTabRestoreService::Delegate::CreateSelectedNavigationInTabCommand( |
| 508 SessionID::id_type tab_id, | 529 SessionID::id_type tab_id, |
| 509 int32 index, | 530 int32 index, |
| 510 base::Time timestamp) { | 531 base::Time timestamp) { |
| 511 SelectedNavigationInTabPayload2 payload; | 532 SelectedNavigationInTabPayload2 payload; |
| 512 payload.id = tab_id; | 533 payload.id = tab_id; |
| 513 payload.index = index; | 534 payload.index = index; |
| 514 payload.timestamp = timestamp.ToInternalValue(); | 535 payload.timestamp = timestamp.ToInternalValue(); |
| 515 SessionCommand* command = | 536 scoped_ptr<SessionCommand> command( |
| 516 new SessionCommand(kCommandSelectedNavigationInTab, sizeof(payload)); | 537 new SessionCommand(kCommandSelectedNavigationInTab, sizeof(payload))); |
| 517 memcpy(command->contents(), &payload, sizeof(payload)); | 538 memcpy(command->contents(), &payload, sizeof(payload)); |
| 518 return command; | 539 return command.Pass(); |
| 519 } | 540 } |
| 520 | 541 |
| 521 // static | 542 // static |
| 522 SessionCommand* | 543 scoped_ptr<SessionCommand> |
| 523 PersistentTabRestoreService::Delegate::CreateRestoredEntryCommand( | 544 PersistentTabRestoreService::Delegate::CreateRestoredEntryCommand( |
| 524 SessionID::id_type entry_id) { | 545 SessionID::id_type entry_id) { |
| 525 RestoredEntryPayload payload = entry_id; | 546 RestoredEntryPayload payload = entry_id; |
| 526 SessionCommand* command = | 547 scoped_ptr<SessionCommand> command( |
| 527 new SessionCommand(kCommandRestoredEntry, sizeof(payload)); | 548 new SessionCommand(kCommandRestoredEntry, sizeof(payload))); |
| 528 memcpy(command->contents(), &payload, sizeof(payload)); | 549 memcpy(command->contents(), &payload, sizeof(payload)); |
| 529 return command; | 550 return command.Pass(); |
| 530 } | 551 } |
| 531 | 552 |
| 532 int PersistentTabRestoreService::Delegate::GetSelectedNavigationIndexToPersist( | 553 int PersistentTabRestoreService::Delegate::GetSelectedNavigationIndexToPersist( |
| 533 const Tab& tab) { | 554 const Tab& tab) { |
| 534 const std::vector<sessions::SerializedNavigationEntry>& navigations = | 555 const std::vector<sessions::SerializedNavigationEntry>& navigations = |
| 535 tab.navigations; | 556 tab.navigations; |
| 536 int selected_index = tab.current_navigation_index; | 557 int selected_index = tab.current_navigation_index; |
| 537 int max_index = static_cast<int>(navigations.size()); | 558 int max_index = static_cast<int>(navigations.size()); |
| 538 | 559 |
| 539 // Find the first navigation to persist. We won't persist the selected | 560 // Find the first navigation to persist. We won't persist the selected |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 break; | 700 break; |
| 680 } | 701 } |
| 681 | 702 |
| 682 case kCommandUpdateTabNavigation: { | 703 case kCommandUpdateTabNavigation: { |
| 683 if (!current_tab) { | 704 if (!current_tab) { |
| 684 // Should be in a tab when we get this. | 705 // Should be in a tab when we get this. |
| 685 return; | 706 return; |
| 686 } | 707 } |
| 687 current_tab->navigations.resize(current_tab->navigations.size() + 1); | 708 current_tab->navigations.resize(current_tab->navigations.size() + 1); |
| 688 SessionID::id_type tab_id; | 709 SessionID::id_type tab_id; |
| 689 if (!RestoreUpdateTabNavigationCommand( | 710 if (!BaseSessionServiceCommands::RestoreUpdateTabNavigationCommand( |
| 690 command, ¤t_tab->navigations.back(), &tab_id)) { | 711 command, |
| 712 ¤t_tab->navigations.back(), |
| 713 &tab_id)) { |
| 691 return; | 714 return; |
| 692 } | 715 } |
| 693 break; | 716 break; |
| 694 } | 717 } |
| 695 | 718 |
| 696 case kCommandPinnedState: { | 719 case kCommandPinnedState: { |
| 697 if (!current_tab) { | 720 if (!current_tab) { |
| 698 // Should be in a tab when we get this. | 721 // Should be in a tab when we get this. |
| 699 return; | 722 return; |
| 700 } | 723 } |
| 701 // NOTE: payload doesn't matter. kCommandPinnedState is only written if | 724 // NOTE: payload doesn't matter. kCommandPinnedState is only written if |
| 702 // tab is pinned. | 725 // tab is pinned. |
| 703 current_tab->pinned = true; | 726 current_tab->pinned = true; |
| 704 break; | 727 break; |
| 705 } | 728 } |
| 706 | 729 |
| 707 case kCommandSetWindowAppName: { | 730 case kCommandSetWindowAppName: { |
| 708 if (!current_window) { | 731 if (!current_window) { |
| 709 // We should have created a window already. | 732 // We should have created a window already. |
| 710 NOTREACHED(); | 733 NOTREACHED(); |
| 711 return; | 734 return; |
| 712 } | 735 } |
| 713 | 736 |
| 714 SessionID::id_type window_id; | 737 SessionID::id_type window_id; |
| 715 std::string app_name; | 738 std::string app_name; |
| 716 if (!RestoreSetWindowAppNameCommand(command, &window_id, &app_name)) | 739 if (!BaseSessionServiceCommands::RestoreSetWindowAppNameCommand( |
| 740 command, |
| 741 &window_id, |
| 742 &app_name)) { |
| 717 return; | 743 return; |
| 744 } |
| 718 | 745 |
| 719 current_window->app_name.swap(app_name); | 746 current_window->app_name.swap(app_name); |
| 720 break; | 747 break; |
| 721 } | 748 } |
| 722 | 749 |
| 723 case kCommandSetExtensionAppID: { | 750 case kCommandSetExtensionAppID: { |
| 724 if (!current_tab) { | 751 if (!current_tab) { |
| 725 // Should be in a tab when we get this. | 752 // Should be in a tab when we get this. |
| 726 return; | 753 return; |
| 727 } | 754 } |
| 728 SessionID::id_type tab_id; | 755 SessionID::id_type tab_id; |
| 729 std::string extension_app_id; | 756 std::string extension_app_id; |
| 730 if (!RestoreSetTabExtensionAppIDCommand(command, &tab_id, | 757 if (!BaseSessionServiceCommands::RestoreSetTabExtensionAppIDCommand( |
| 731 &extension_app_id)) { | 758 command, |
| 759 &tab_id, |
| 760 &extension_app_id)) { |
| 732 return; | 761 return; |
| 733 } | 762 } |
| 734 current_tab->extension_app_id.swap(extension_app_id); | 763 current_tab->extension_app_id.swap(extension_app_id); |
| 735 break; | 764 break; |
| 736 } | 765 } |
| 737 | 766 |
| 738 case kCommandSetTabUserAgentOverride: { | 767 case kCommandSetTabUserAgentOverride: { |
| 739 if (!current_tab) { | 768 if (!current_tab) { |
| 740 // Should be in a tab when we get this. | 769 // Should be in a tab when we get this. |
| 741 return; | 770 return; |
| 742 } | 771 } |
| 743 SessionID::id_type tab_id; | 772 SessionID::id_type tab_id; |
| 744 std::string user_agent_override; | 773 std::string user_agent_override; |
| 745 if (!RestoreSetTabUserAgentOverrideCommand(command, &tab_id, | 774 if (!BaseSessionServiceCommands::RestoreSetTabUserAgentOverrideCommand( |
| 746 &user_agent_override)) { | 775 command, |
| 776 &tab_id, |
| 777 &user_agent_override)) { |
| 747 return; | 778 return; |
| 748 } | 779 } |
| 749 current_tab->user_agent_override.swap(user_agent_override); | 780 current_tab->user_agent_override.swap(user_agent_override); |
| 750 break; | 781 break; |
| 751 } | 782 } |
| 752 | 783 |
| 753 default: | 784 default: |
| 754 // Unknown type, usually indicates corruption of file. Ignore it. | 785 // Unknown type, usually indicates corruption of file. Ignore it. |
| 755 return; | 786 return; |
| 756 } | 787 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 } | 1023 } |
| 993 | 1024 |
| 994 void PersistentTabRestoreService::PruneEntries() { | 1025 void PersistentTabRestoreService::PruneEntries() { |
| 995 helper_.PruneEntries(); | 1026 helper_.PruneEntries(); |
| 996 } | 1027 } |
| 997 | 1028 |
| 998 KeyedService* TabRestoreServiceFactory::BuildServiceInstanceFor( | 1029 KeyedService* TabRestoreServiceFactory::BuildServiceInstanceFor( |
| 999 content::BrowserContext* profile) const { | 1030 content::BrowserContext* profile) const { |
| 1000 return new PersistentTabRestoreService(static_cast<Profile*>(profile), NULL); | 1031 return new PersistentTabRestoreService(static_cast<Profile*>(profile), NULL); |
| 1001 } | 1032 } |
| OLD | NEW |