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/session_service.h" | 5 #include "chrome/browser/sessions/session_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 11 matching lines...) Expand all Loading... | |
22 #include "chrome/browser/defaults.h" | 22 #include "chrome/browser/defaults.h" |
23 #include "chrome/browser/extensions/tab_helper.h" | 23 #include "chrome/browser/extensions/tab_helper.h" |
24 #include "chrome/browser/prefs/session_startup_pref.h" | 24 #include "chrome/browser/prefs/session_startup_pref.h" |
25 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
26 #include "chrome/browser/profiles/profile_manager.h" | 26 #include "chrome/browser/profiles/profile_manager.h" |
27 #include "chrome/browser/sessions/base_session_service_delegate_impl.h" | 27 #include "chrome/browser/sessions/base_session_service_delegate_impl.h" |
28 #include "chrome/browser/sessions/session_backend.h" | 28 #include "chrome/browser/sessions/session_backend.h" |
29 #include "chrome/browser/sessions/session_command.h" | 29 #include "chrome/browser/sessions/session_command.h" |
30 #include "chrome/browser/sessions/session_data_deleter.h" | 30 #include "chrome/browser/sessions/session_data_deleter.h" |
31 #include "chrome/browser/sessions/session_restore.h" | 31 #include "chrome/browser/sessions/session_restore.h" |
32 #include "chrome/browser/sessions/session_service_utils.h" | |
32 #include "chrome/browser/sessions/session_tab_helper.h" | 33 #include "chrome/browser/sessions/session_tab_helper.h" |
33 #include "chrome/browser/sessions/session_types.h" | 34 #include "chrome/browser/sessions/session_types.h" |
34 #include "chrome/browser/ui/browser_iterator.h" | 35 #include "chrome/browser/ui/browser_iterator.h" |
35 #include "chrome/browser/ui/browser_list.h" | 36 #include "chrome/browser/ui/browser_list.h" |
36 #include "chrome/browser/ui/browser_tabstrip.h" | 37 #include "chrome/browser/ui/browser_tabstrip.h" |
37 #include "chrome/browser/ui/browser_window.h" | 38 #include "chrome/browser/ui/browser_window.h" |
38 #include "chrome/browser/ui/host_desktop.h" | 39 #include "chrome/browser/ui/host_desktop.h" |
39 #include "chrome/browser/ui/startup/startup_browser_creator.h" | 40 #include "chrome/browser/ui/startup/startup_browser_creator.h" |
40 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 41 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
41 #include "components/sessions/content/content_serialized_navigation_builder.h" | 42 #include "components/sessions/content/content_serialized_navigation_builder.h" |
42 #include "components/startup_metric_utils/startup_metric_utils.h" | 43 #include "components/startup_metric_utils/startup_metric_utils.h" |
43 #include "content/public/browser/navigation_details.h" | 44 #include "content/public/browser/navigation_details.h" |
44 #include "content/public/browser/navigation_entry.h" | 45 #include "content/public/browser/navigation_entry.h" |
45 #include "content/public/browser/notification_details.h" | 46 #include "content/public/browser/notification_details.h" |
46 #include "content/public/browser/notification_service.h" | 47 #include "content/public/browser/notification_service.h" |
47 #include "content/public/browser/session_storage_namespace.h" | 48 #include "content/public/browser/session_storage_namespace.h" |
48 #include "content/public/browser/web_contents.h" | 49 #include "content/public/browser/web_contents.h" |
49 #include "extensions/common/extension.h" | 50 #include "extensions/common/extension.h" |
50 | 51 |
51 #if defined(OS_MACOSX) | 52 #if defined(OS_MACOSX) |
52 #include "chrome/browser/app_controller_mac.h" | 53 #include "chrome/browser/app_controller_mac.h" |
53 #endif | 54 #endif |
54 | 55 |
55 using base::Time; | 56 using base::Time; |
56 using content::NavigationEntry; | 57 using content::NavigationEntry; |
57 using content::WebContents; | 58 using content::WebContents; |
58 using sessions::ContentSerializedNavigationBuilder; | 59 using sessions::ContentSerializedNavigationBuilder; |
59 using sessions::SerializedNavigationEntry; | 60 using sessions::SerializedNavigationEntry; |
60 | 61 |
61 // Identifier for commands written to file. | |
62 static const SessionCommand::id_type kCommandSetTabWindow = 0; | |
63 // OBSOLETE Superseded by kCommandSetWindowBounds3. | |
64 // static const SessionCommand::id_type kCommandSetWindowBounds = 1; | |
65 static const SessionCommand::id_type kCommandSetTabIndexInWindow = 2; | |
66 // OBSOLETE Superseded kCommandTabClosed/kCommandWindowClosed commands. | |
67 // static const SessionCommand::id_type kCommandTabClosedObsolete = 3; | |
68 // static const SessionCommand::id_type kCommandWindowClosedObsolete = 4; | |
69 static const SessionCommand::id_type | |
70 kCommandTabNavigationPathPrunedFromBack = 5; | |
71 static const SessionCommand::id_type kCommandUpdateTabNavigation = 6; | |
72 static const SessionCommand::id_type kCommandSetSelectedNavigationIndex = 7; | |
73 static const SessionCommand::id_type kCommandSetSelectedTabInIndex = 8; | |
74 static const SessionCommand::id_type kCommandSetWindowType = 9; | |
75 // OBSOLETE Superseded by kCommandSetWindowBounds3. Except for data migration. | |
76 // static const SessionCommand::id_type kCommandSetWindowBounds2 = 10; | |
77 static const SessionCommand::id_type | |
78 kCommandTabNavigationPathPrunedFromFront = 11; | |
79 static const SessionCommand::id_type kCommandSetPinnedState = 12; | |
80 static const SessionCommand::id_type kCommandSetExtensionAppID = 13; | |
81 static const SessionCommand::id_type kCommandSetWindowBounds3 = 14; | |
82 static const SessionCommand::id_type kCommandSetWindowAppName = 15; | |
83 static const SessionCommand::id_type kCommandTabClosed = 16; | |
84 static const SessionCommand::id_type kCommandWindowClosed = 17; | |
85 static const SessionCommand::id_type kCommandSetTabUserAgentOverride = 18; | |
86 static const SessionCommand::id_type kCommandSessionStorageAssociated = 19; | |
87 static const SessionCommand::id_type kCommandSetActiveWindow = 20; | |
88 | |
89 // Every kWritesPerReset commands triggers recreating the file. | 62 // Every kWritesPerReset commands triggers recreating the file. |
90 static const int kWritesPerReset = 250; | 63 static const int kWritesPerReset = 250; |
91 | 64 |
92 namespace { | |
93 | |
94 // Various payload structures. | |
95 struct ClosedPayload { | |
96 SessionID::id_type id; | |
97 int64 close_time; | |
98 }; | |
99 | |
100 struct WindowBoundsPayload2 { | |
101 SessionID::id_type window_id; | |
102 int32 x; | |
103 int32 y; | |
104 int32 w; | |
105 int32 h; | |
106 bool is_maximized; | |
107 }; | |
108 | |
109 struct WindowBoundsPayload3 { | |
110 SessionID::id_type window_id; | |
111 int32 x; | |
112 int32 y; | |
113 int32 w; | |
114 int32 h; | |
115 int32 show_state; | |
116 }; | |
117 | |
118 typedef SessionID::id_type ActiveWindowPayload; | |
119 | |
120 struct IDAndIndexPayload { | |
121 SessionID::id_type id; | |
122 int32 index; | |
123 }; | |
124 | |
125 typedef IDAndIndexPayload TabIndexInWindowPayload; | |
126 | |
127 typedef IDAndIndexPayload TabNavigationPathPrunedFromBackPayload; | |
128 | |
129 typedef IDAndIndexPayload SelectedNavigationIndexPayload; | |
130 | |
131 typedef IDAndIndexPayload SelectedTabInIndexPayload; | |
132 | |
133 typedef IDAndIndexPayload WindowTypePayload; | |
134 | |
135 typedef IDAndIndexPayload TabNavigationPathPrunedFromFrontPayload; | |
136 | |
137 struct PinnedStatePayload { | |
138 SessionID::id_type tab_id; | |
139 bool pinned_state; | |
140 }; | |
141 | |
142 // Persisted versions of ui::WindowShowState that are written to disk and can | |
143 // never change. | |
144 enum PersistedWindowShowState { | |
145 // SHOW_STATE_DEFAULT (0) never persisted. | |
146 PERSISTED_SHOW_STATE_NORMAL = 1, | |
147 PERSISTED_SHOW_STATE_MINIMIZED = 2, | |
148 PERSISTED_SHOW_STATE_MAXIMIZED = 3, | |
149 // SHOW_STATE_INACTIVE (4) never persisted. | |
150 PERSISTED_SHOW_STATE_FULLSCREEN = 5, | |
151 PERSISTED_SHOW_STATE_DETACHED_DEPRECATED = 6, | |
152 PERSISTED_SHOW_STATE_END = 6 | |
153 }; | |
154 | |
155 // Assert to ensure PersistedWindowShowState is updated if ui::WindowShowState | |
156 // is changed. | |
157 COMPILE_ASSERT(ui::SHOW_STATE_END == | |
158 static_cast<ui::WindowShowState>(PERSISTED_SHOW_STATE_END), | |
159 persisted_show_state_mismatch); | |
160 | |
161 // Returns the show state to store to disk based |state|. | |
162 PersistedWindowShowState ShowStateToPersistedShowState( | |
163 ui::WindowShowState state) { | |
164 switch (state) { | |
165 case ui::SHOW_STATE_NORMAL: | |
166 return PERSISTED_SHOW_STATE_NORMAL; | |
167 case ui::SHOW_STATE_MINIMIZED: | |
168 return PERSISTED_SHOW_STATE_MINIMIZED; | |
169 case ui::SHOW_STATE_MAXIMIZED: | |
170 return PERSISTED_SHOW_STATE_MAXIMIZED; | |
171 case ui::SHOW_STATE_FULLSCREEN: | |
172 return PERSISTED_SHOW_STATE_FULLSCREEN; | |
173 | |
174 case ui::SHOW_STATE_DEFAULT: | |
175 case ui::SHOW_STATE_INACTIVE: | |
176 return PERSISTED_SHOW_STATE_NORMAL; | |
177 | |
178 case ui::SHOW_STATE_END: | |
179 break; | |
180 } | |
181 NOTREACHED(); | |
182 return PERSISTED_SHOW_STATE_NORMAL; | |
183 } | |
184 | |
185 // Lints show state values when read back from persited disk. | |
186 ui::WindowShowState PersistedShowStateToShowState(int state) { | |
187 switch (state) { | |
188 case PERSISTED_SHOW_STATE_NORMAL: | |
189 return ui::SHOW_STATE_NORMAL; | |
190 case PERSISTED_SHOW_STATE_MINIMIZED: | |
191 return ui::SHOW_STATE_MINIMIZED; | |
192 case PERSISTED_SHOW_STATE_MAXIMIZED: | |
193 return ui::SHOW_STATE_MAXIMIZED; | |
194 case PERSISTED_SHOW_STATE_FULLSCREEN: | |
195 return ui::SHOW_STATE_FULLSCREEN; | |
196 case PERSISTED_SHOW_STATE_DETACHED_DEPRECATED: | |
197 return ui::SHOW_STATE_NORMAL; | |
198 } | |
199 NOTREACHED(); | |
200 return ui::SHOW_STATE_NORMAL; | |
201 } | |
202 | |
203 } // namespace | |
204 | |
205 // SessionService ------------------------------------------------------------- | 65 // SessionService ------------------------------------------------------------- |
206 | 66 |
207 SessionService::SessionService(Profile* profile) | 67 SessionService::SessionService(Profile* profile) |
208 : BaseSessionService( | 68 : BaseSessionService( |
209 SESSION_RESTORE, | 69 SESSION_RESTORE, |
210 profile->GetPath(), | 70 profile->GetPath(), |
211 scoped_ptr<BaseSessionServiceDelegate>( | 71 scoped_ptr<BaseSessionServiceDelegate>( |
212 new BaseSessionServiceDelegateImpl(true))), | 72 new BaseSessionServiceDelegateImpl(true))), |
213 profile_(profile), | 73 profile_(profile), |
214 has_open_trackable_browsers_(false), | 74 has_open_trackable_browsers_(false), |
(...skipping 25 matching lines...) Expand all Loading... | |
240 Init(); | 100 Init(); |
241 } | 101 } |
242 | 102 |
243 SessionService::~SessionService() { | 103 SessionService::~SessionService() { |
244 // The BrowserList should outlive the SessionService since it's static and | 104 // The BrowserList should outlive the SessionService since it's static and |
245 // the SessionService is a KeyedService. | 105 // the SessionService is a KeyedService. |
246 BrowserList::RemoveObserver(this); | 106 BrowserList::RemoveObserver(this); |
247 Save(); | 107 Save(); |
248 } | 108 } |
249 | 109 |
110 bool SessionService::ShouldNewWindowStartSession() { | |
sky
2014/10/29 15:44:21
You're reordering of this file is making it hard f
Mr4D (OOO till 08-26)
2014/10/29 19:35:30
Done.
| |
111 // ChromeOS and OSX have different ideas of application lifetime than | |
112 // the other platforms. | |
113 // On ChromeOS opening a new window should never start a new session. | |
114 #if defined(OS_CHROMEOS) | |
115 if (!force_browser_not_alive_with_no_windows_) | |
116 return false; | |
117 #endif | |
118 if (!has_open_trackable_browsers_ && | |
119 !StartupBrowserCreator::InSynchronousProfileLaunch() && | |
120 !SessionRestore::IsRestoring(profile()) | |
121 #if defined(OS_MACOSX) | |
122 // On OSX, a new window should not start a new session if it was opened | |
123 // from the dock or the menubar. | |
124 && !app_controller_mac::IsOpeningNewWindow() | |
125 #endif // OS_MACOSX | |
126 ) { | |
127 return true; | |
128 } | |
129 return false; | |
130 } | |
131 | |
250 bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open) { | 132 bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open) { |
251 return RestoreIfNecessary(urls_to_open, NULL); | 133 return RestoreIfNecessary(urls_to_open, NULL); |
252 } | 134 } |
253 | 135 |
254 void SessionService::ResetFromCurrentBrowsers() { | 136 void SessionService::ResetFromCurrentBrowsers() { |
255 ScheduleReset(); | 137 ScheduleResetCommands(); |
256 } | 138 } |
257 | 139 |
258 void SessionService::MoveCurrentSessionToLastSession() { | 140 void SessionService::MoveCurrentSessionToLastSession() { |
259 pending_tab_close_ids_.clear(); | 141 pending_tab_close_ids_.clear(); |
260 window_closing_ids_.clear(); | 142 window_closing_ids_.clear(); |
261 pending_window_close_ids_.clear(); | 143 pending_window_close_ids_.clear(); |
262 | 144 |
263 Save(); | 145 Save(); |
264 | 146 |
265 RunTaskOnBackendThread( | 147 RunTaskOnBackendThread( |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
336 // tab closed. | 218 // tab closed. |
337 pending_tab_close_ids_.insert(tab_id.id()); | 219 pending_tab_close_ids_.insert(tab_id.id()); |
338 has_open_trackable_browsers_ = false; | 220 has_open_trackable_browsers_ = false; |
339 } | 221 } |
340 } | 222 } |
341 | 223 |
342 void SessionService::WindowOpened(Browser* browser) { | 224 void SessionService::WindowOpened(Browser* browser) { |
343 if (!ShouldTrackBrowser(browser)) | 225 if (!ShouldTrackBrowser(browser)) |
344 return; | 226 return; |
345 | 227 |
346 AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL; | 228 SessionServiceCommands::AppType app_type = |
229 browser->is_app() ? SessionServiceCommands::TYPE_APP : | |
230 SessionServiceCommands::TYPE_NORMAL; | |
347 RestoreIfNecessary(std::vector<GURL>(), browser); | 231 RestoreIfNecessary(std::vector<GURL>(), browser); |
348 SetWindowType(browser->session_id(), browser->type(), app_type); | 232 SetWindowType(browser->session_id(), browser->type(), app_type); |
349 SetWindowAppName(browser->session_id(), browser->app_name()); | 233 SetWindowAppName(browser->session_id(), browser->app_name()); |
350 } | 234 } |
351 | 235 |
352 void SessionService::WindowClosing(const SessionID& window_id) { | 236 void SessionService::WindowClosing(const SessionID& window_id) { |
353 if (!ShouldTrackChangesToWindow(window_id)) | 237 if (!ShouldTrackChangesToWindow(window_id)) |
354 return; | 238 return; |
355 | 239 |
356 // The window is about to close. If there are other tabbed browsers with the | 240 // The window is about to close. If there are other tabbed browsers with the |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 // We'll hit this if user closed the last tab in a window. | 293 // We'll hit this if user closed the last tab in a window. |
410 has_open_trackable_browsers_ = HasOpenTrackableBrowsers(window_id); | 294 has_open_trackable_browsers_ = HasOpenTrackableBrowsers(window_id); |
411 if (!has_open_trackable_browsers_) | 295 if (!has_open_trackable_browsers_) |
412 pending_window_close_ids_.insert(window_id.id()); | 296 pending_window_close_ids_.insert(window_id.id()); |
413 else | 297 else |
414 ScheduleCommand(CreateWindowClosedCommand(window_id.id())); | 298 ScheduleCommand(CreateWindowClosedCommand(window_id.id())); |
415 } | 299 } |
416 MaybeDeleteSessionOnlyData(); | 300 MaybeDeleteSessionOnlyData(); |
417 } | 301 } |
418 | 302 |
303 void SessionService::TabInserted(WebContents* contents) { | |
304 SessionTabHelper* session_tab_helper = | |
305 SessionTabHelper::FromWebContents(contents); | |
306 if (!ShouldTrackChangesToWindow(session_tab_helper->window_id())) | |
307 return; | |
308 SetTabWindow(session_tab_helper->window_id(), | |
309 session_tab_helper->session_id()); | |
310 extensions::TabHelper* extensions_tab_helper = | |
311 extensions::TabHelper::FromWebContents(contents); | |
312 if (extensions_tab_helper && | |
313 extensions_tab_helper->extension_app()) { | |
314 SetTabExtensionAppID( | |
315 session_tab_helper->window_id(), | |
316 session_tab_helper->session_id(), | |
317 extensions_tab_helper->extension_app()->id()); | |
318 } | |
319 | |
320 // Record the association between the SessionStorageNamespace and the | |
321 // tab. | |
322 // | |
323 // TODO(ajwong): This should be processing the whole map rather than | |
324 // just the default. This in particular will not work for tabs with only | |
325 // isolated apps which won't have a default partition. | |
326 content::SessionStorageNamespace* session_storage_namespace = | |
327 contents->GetController().GetDefaultSessionStorageNamespace(); | |
328 ScheduleCommand(CreateSessionStorageAssociatedCommand( | |
329 session_tab_helper->session_id(), | |
330 session_storage_namespace->persistent_id())); | |
331 session_storage_namespace->SetShouldPersist(true); | |
332 } | |
333 | |
334 void SessionService::TabClosing(WebContents* contents) { | |
335 // Allow the associated sessionStorage to get deleted; it won't be needed | |
336 // in the session restore. | |
337 content::SessionStorageNamespace* session_storage_namespace = | |
338 contents->GetController().GetDefaultSessionStorageNamespace(); | |
339 session_storage_namespace->SetShouldPersist(false); | |
340 SessionTabHelper* session_tab_helper = | |
341 SessionTabHelper::FromWebContents(contents); | |
342 TabClosed(session_tab_helper->window_id(), | |
343 session_tab_helper->session_id(), | |
344 contents->GetClosedByUserGesture()); | |
345 RecordSessionUpdateHistogramData(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
346 &last_updated_tab_closed_time_); | |
347 } | |
348 | |
419 void SessionService::SetWindowType(const SessionID& window_id, | 349 void SessionService::SetWindowType(const SessionID& window_id, |
420 Browser::Type type, | 350 Browser::Type type, |
421 AppType app_type) { | 351 SessionServiceCommands::AppType app_type) { |
422 if (!should_track_changes_for_browser_type(type, app_type)) | 352 SessionWindow::WindowType window_type = WindowTypeForBrowserType(type); |
353 if (!ShouldRestoreWindowOfType(window_type, app_type)) | |
423 return; | 354 return; |
424 | 355 |
425 windows_tracking_.insert(window_id.id()); | 356 windows_tracking_.insert(window_id.id()); |
426 | 357 |
427 // The user created a new tabbed browser with our profile. Commit any | 358 // The user created a new tabbed browser with our profile. Commit any |
428 // pending closes. | 359 // pending closes. |
429 CommitPendingCloses(); | 360 CommitPendingCloses(); |
430 | 361 |
431 has_open_trackable_browsers_ = true; | 362 has_open_trackable_browsers_ = true; |
432 move_on_new_browser_ = true; | 363 move_on_new_browser_ = true; |
433 | 364 |
434 ScheduleCommand( | 365 ScheduleCommand(CreateSetWindowTypeCommand(window_id, window_type)); |
435 CreateSetWindowTypeCommand(window_id, WindowTypeForBrowserType(type))); | |
436 } | 366 } |
437 | 367 |
438 void SessionService::SetWindowAppName( | 368 void SessionService::SetWindowAppName( |
439 const SessionID& window_id, | 369 const SessionID& window_id, |
440 const std::string& app_name) { | 370 const std::string& app_name) { |
441 if (!ShouldTrackChangesToWindow(window_id)) | 371 if (!ShouldTrackChangesToWindow(window_id)) |
442 return; | 372 return; |
443 | 373 |
444 ScheduleCommand(CreateSetTabExtensionAppIDCommand( | 374 ScheduleCommand(CreateSetWindowAppNameCommand(window_id, app_name)); |
445 kCommandSetWindowAppName, | |
446 window_id.id(), | |
447 app_name)); | |
448 } | 375 } |
449 | 376 |
450 void SessionService::TabNavigationPathPrunedFromBack(const SessionID& window_id, | 377 void SessionService::TabNavigationPathPrunedFromBack(const SessionID& window_id, |
451 const SessionID& tab_id, | 378 const SessionID& tab_id, |
452 int count) { | 379 int count) { |
453 if (!ShouldTrackChangesToWindow(window_id)) | 380 if (!ShouldTrackChangesToWindow(window_id)) |
454 return; | 381 return; |
455 | 382 |
456 TabNavigationPathPrunedFromBackPayload payload = { 0 }; | 383 ScheduleCommand(CreateTabNavigationPathPrunedFromBackCommand(tab_id, count)); |
457 payload.id = tab_id.id(); | |
458 payload.index = count; | |
459 SessionCommand* command = | |
460 new SessionCommand(kCommandTabNavigationPathPrunedFromBack, | |
461 sizeof(payload)); | |
462 memcpy(command->contents(), &payload, sizeof(payload)); | |
463 ScheduleCommand(command); | |
464 } | 384 } |
465 | 385 |
466 void SessionService::TabNavigationPathPrunedFromFront( | 386 void SessionService::TabNavigationPathPrunedFromFront( |
467 const SessionID& window_id, | 387 const SessionID& window_id, |
468 const SessionID& tab_id, | 388 const SessionID& tab_id, |
469 int count) { | 389 int count) { |
470 if (!ShouldTrackChangesToWindow(window_id)) | 390 if (!ShouldTrackChangesToWindow(window_id)) |
471 return; | 391 return; |
472 | 392 |
473 // Update the range of indices. | 393 // Update the range of indices. |
474 if (tab_to_available_range_.find(tab_id.id()) != | 394 if (tab_to_available_range_.find(tab_id.id()) != |
475 tab_to_available_range_.end()) { | 395 tab_to_available_range_.end()) { |
476 std::pair<int, int>& range = tab_to_available_range_[tab_id.id()]; | 396 std::pair<int, int>& range = tab_to_available_range_[tab_id.id()]; |
477 range.first = std::max(0, range.first - count); | 397 range.first = std::max(0, range.first - count); |
478 range.second = std::max(0, range.second - count); | 398 range.second = std::max(0, range.second - count); |
479 } | 399 } |
480 | 400 |
481 TabNavigationPathPrunedFromFrontPayload payload = { 0 }; | 401 ScheduleCommand(CreateTabNavigationPathPrunedFromFrontCommand(tab_id, count)); |
482 payload.id = tab_id.id(); | |
483 payload.index = count; | |
484 SessionCommand* command = | |
485 new SessionCommand(kCommandTabNavigationPathPrunedFromFront, | |
486 sizeof(payload)); | |
487 memcpy(command->contents(), &payload, sizeof(payload)); | |
488 ScheduleCommand(command); | |
489 } | 402 } |
490 | 403 |
491 void SessionService::UpdateTabNavigation( | 404 void SessionService::UpdateTabNavigation( |
492 const SessionID& window_id, | 405 const SessionID& window_id, |
493 const SessionID& tab_id, | 406 const SessionID& tab_id, |
494 const SerializedNavigationEntry& navigation) { | 407 const SerializedNavigationEntry& navigation) { |
495 if (!ShouldTrackEntry(navigation.virtual_url()) || | 408 if (!ShouldTrackEntry(navigation.virtual_url()) || |
496 !ShouldTrackChangesToWindow(window_id)) { | 409 !ShouldTrackChangesToWindow(window_id)) { |
497 return; | 410 return; |
498 } | 411 } |
499 | 412 |
500 if (tab_to_available_range_.find(tab_id.id()) != | 413 if (tab_to_available_range_.find(tab_id.id()) != |
501 tab_to_available_range_.end()) { | 414 tab_to_available_range_.end()) { |
502 std::pair<int, int>& range = tab_to_available_range_[tab_id.id()]; | 415 std::pair<int, int>& range = tab_to_available_range_[tab_id.id()]; |
503 range.first = std::min(navigation.index(), range.first); | 416 range.first = std::min(navigation.index(), range.first); |
504 range.second = std::max(navigation.index(), range.second); | 417 range.second = std::max(navigation.index(), range.second); |
505 } | 418 } |
506 ScheduleCommand(CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, | 419 ScheduleCommand(CreateUpdateTabNavigationCommand(tab_id, navigation)); |
507 tab_id.id(), navigation)); | |
508 } | 420 } |
509 | 421 |
510 void SessionService::TabRestored(WebContents* tab, bool pinned) { | 422 void SessionService::TabRestored(WebContents* tab, bool pinned) { |
511 SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(tab); | 423 SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(tab); |
512 if (!ShouldTrackChangesToWindow(session_tab_helper->window_id())) | 424 if (!ShouldTrackChangesToWindow(session_tab_helper->window_id())) |
513 return; | 425 return; |
514 | 426 |
515 BuildCommandsForTab(session_tab_helper->window_id(), tab, -1, | 427 BuildCommandsForTab(session_tab_helper->window_id(), tab, -1, |
516 pinned, &pending_commands(), NULL); | 428 pinned, &pending_commands(), NULL); |
517 StartSaveTimer(); | 429 StartSaveTimer(); |
(...skipping 16 matching lines...) Expand all Loading... | |
534 } | 446 } |
535 } | 447 } |
536 ScheduleCommand(CreateSetSelectedNavigationIndexCommand(tab_id, index)); | 448 ScheduleCommand(CreateSetSelectedNavigationIndexCommand(tab_id, index)); |
537 } | 449 } |
538 | 450 |
539 void SessionService::SetSelectedTabInWindow(const SessionID& window_id, | 451 void SessionService::SetSelectedTabInWindow(const SessionID& window_id, |
540 int index) { | 452 int index) { |
541 if (!ShouldTrackChangesToWindow(window_id)) | 453 if (!ShouldTrackChangesToWindow(window_id)) |
542 return; | 454 return; |
543 | 455 |
544 ScheduleCommand(CreateSetSelectedTabInWindow(window_id, index)); | 456 ScheduleCommand(CreateSetSelectedTabInWindowCommand(window_id, index)); |
545 } | 457 } |
546 | 458 |
547 void SessionService::SetTabUserAgentOverride( | 459 void SessionService::SetTabUserAgentOverride( |
548 const SessionID& window_id, | 460 const SessionID& window_id, |
549 const SessionID& tab_id, | 461 const SessionID& tab_id, |
550 const std::string& user_agent_override) { | 462 const std::string& user_agent_override) { |
551 if (!ShouldTrackChangesToWindow(window_id)) | 463 if (!ShouldTrackChangesToWindow(window_id)) |
552 return; | 464 return; |
553 | 465 |
554 ScheduleCommand(CreateSetTabUserAgentOverrideCommand( | 466 ScheduleCommand(CreateSetTabUserAgentOverrideCommand(tab_id, |
555 kCommandSetTabUserAgentOverride, tab_id.id(), user_agent_override)); | 467 user_agent_override)); |
468 } | |
469 | |
470 void SessionService::SetTabExtensionAppID( | |
471 const SessionID& window_id, | |
472 const SessionID& tab_id, | |
473 const std::string& extension_app_id) { | |
474 if (!ShouldTrackChangesToWindow(window_id)) | |
475 return; | |
476 | |
477 ScheduleCommand(CreateSetTabExtensionAppIDCommand(tab_id, extension_app_id)); | |
556 } | 478 } |
557 | 479 |
558 base::CancelableTaskTracker::TaskId SessionService::GetLastSession( | 480 base::CancelableTaskTracker::TaskId SessionService::GetLastSession( |
559 const SessionCallback& callback, | 481 const SessionCallback& callback, |
560 base::CancelableTaskTracker* tracker) { | 482 base::CancelableTaskTracker* tracker) { |
561 // OnGotSessionCommands maps the SessionCommands to browser state, then run | 483 // OnGotSessionCommands maps the SessionCommands to browser state, then run |
562 // the callback. | 484 // the callback. |
563 return ScheduleGetLastSessionCommands( | 485 return ScheduleGetLastSessionCommands( |
564 base::Bind(&SessionService::OnGotSessionCommands, | 486 base::Bind(&SessionService::OnGotSessionCommands, |
565 weak_factory_.GetWeakPtr(), callback), | 487 weak_factory_.GetWeakPtr(), callback), |
566 tracker); | 488 tracker); |
567 } | 489 } |
568 | 490 |
491 bool SessionService::ShouldRestoreWindowOfType( | |
492 SessionWindow::WindowType window_type, | |
493 SessionServiceCommands::AppType app_type) const { | |
494 #if defined(OS_CHROMEOS) | |
495 // Restore app popups for ChromeOS alone. | |
496 if (window_type == SessionWindow::TYPE_POPUP && app_type == TYPE_APP) | |
497 return true; | |
498 #endif | |
499 | |
500 return window_type == SessionWindow::TYPE_TABBED; | |
501 } | |
502 | |
569 void SessionService::Save() { | 503 void SessionService::Save() { |
570 bool had_commands = !pending_commands().empty(); | 504 bool had_commands = !pending_commands().empty(); |
571 BaseSessionService::Save(); | 505 BaseSessionService::Save(); |
572 if (had_commands) { | 506 if (had_commands) { |
573 RecordSessionUpdateHistogramData(chrome::NOTIFICATION_SESSION_SERVICE_SAVED, | 507 RecordSessionUpdateHistogramData(chrome::NOTIFICATION_SESSION_SERVICE_SAVED, |
574 &last_updated_save_time_); | 508 &last_updated_save_time_); |
575 content::NotificationService::current()->Notify( | 509 content::NotificationService::current()->Notify( |
576 chrome::NOTIFICATION_SESSION_SERVICE_SAVED, | 510 chrome::NOTIFICATION_SESSION_SERVICE_SAVED, |
577 content::Source<Profile>(profile()), | 511 content::Source<Profile>(profile()), |
578 content::NotificationService::NoDetails()); | 512 content::NotificationService::NoDetails()); |
(...skipping 12 matching lines...) Expand all Loading... | |
591 this, chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED, | 525 this, chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED, |
592 content::NotificationService::AllSources()); | 526 content::NotificationService::AllSources()); |
593 | 527 |
594 BrowserList::AddObserver(this); | 528 BrowserList::AddObserver(this); |
595 } | 529 } |
596 | 530 |
597 bool SessionService::processed_any_commands() { | 531 bool SessionService::processed_any_commands() { |
598 return backend()->inited() || !pending_commands().empty(); | 532 return backend()->inited() || !pending_commands().empty(); |
599 } | 533 } |
600 | 534 |
601 bool SessionService::ShouldNewWindowStartSession() { | |
602 // ChromeOS and OSX have different ideas of application lifetime than | |
603 // the other platforms. | |
604 // On ChromeOS opening a new window should never start a new session. | |
605 #if defined(OS_CHROMEOS) | |
606 if (!force_browser_not_alive_with_no_windows_) | |
607 return false; | |
608 #endif | |
609 if (!has_open_trackable_browsers_ && | |
610 !StartupBrowserCreator::InSynchronousProfileLaunch() && | |
611 !SessionRestore::IsRestoring(profile()) | |
612 #if defined(OS_MACOSX) | |
613 // On OSX, a new window should not start a new session if it was opened | |
614 // from the dock or the menubar. | |
615 && !app_controller_mac::IsOpeningNewWindow() | |
616 #endif // OS_MACOSX | |
617 ) { | |
618 return true; | |
619 } | |
620 return false; | |
621 } | |
622 | |
623 bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open, | 535 bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open, |
624 Browser* browser) { | 536 Browser* browser) { |
625 if (ShouldNewWindowStartSession()) { | 537 if (ShouldNewWindowStartSession()) { |
626 // We're going from no tabbed browsers to a tabbed browser (and not in | 538 // We're going from no tabbed browsers to a tabbed browser (and not in |
627 // process startup), restore the last session. | 539 // process startup), restore the last session. |
628 if (move_on_new_browser_) { | 540 if (move_on_new_browser_) { |
629 // Make the current session the last. | 541 // Make the current session the last. |
630 MoveCurrentSessionToLastSession(); | 542 MoveCurrentSessionToLastSession(); |
631 move_on_new_browser_ = false; | 543 move_on_new_browser_ = false; |
632 } | 544 } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
745 default: | 657 default: |
746 NOTREACHED(); | 658 NOTREACHED(); |
747 } | 659 } |
748 } | 660 } |
749 | 661 |
750 void SessionService::OnBrowserSetLastActive(Browser* browser) { | 662 void SessionService::OnBrowserSetLastActive(Browser* browser) { |
751 if (ShouldTrackBrowser(browser)) | 663 if (ShouldTrackBrowser(browser)) |
752 ScheduleCommand(CreateSetActiveWindowCommand(browser->session_id())); | 664 ScheduleCommand(CreateSetActiveWindowCommand(browser->session_id())); |
753 } | 665 } |
754 | 666 |
755 void SessionService::SetTabExtensionAppID( | |
756 const SessionID& window_id, | |
757 const SessionID& tab_id, | |
758 const std::string& extension_app_id) { | |
759 if (!ShouldTrackChangesToWindow(window_id)) | |
760 return; | |
761 | |
762 ScheduleCommand(CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID, | |
763 tab_id.id(), extension_app_id)); | |
764 } | |
765 | |
766 SessionCommand* SessionService::CreateSetSelectedTabInWindow( | |
767 const SessionID& window_id, | |
768 int index) { | |
769 SelectedTabInIndexPayload payload = { 0 }; | |
770 payload.id = window_id.id(); | |
771 payload.index = index; | |
772 SessionCommand* command = new SessionCommand(kCommandSetSelectedTabInIndex, | |
773 sizeof(payload)); | |
774 memcpy(command->contents(), &payload, sizeof(payload)); | |
775 return command; | |
776 } | |
777 | |
778 SessionCommand* SessionService::CreateSetTabWindowCommand( | |
779 const SessionID& window_id, | |
780 const SessionID& tab_id) { | |
781 SessionID::id_type payload[] = { window_id.id(), tab_id.id() }; | |
782 SessionCommand* command = | |
783 new SessionCommand(kCommandSetTabWindow, sizeof(payload)); | |
784 memcpy(command->contents(), payload, sizeof(payload)); | |
785 return command; | |
786 } | |
787 | |
788 SessionCommand* SessionService::CreateSetWindowBoundsCommand( | |
789 const SessionID& window_id, | |
790 const gfx::Rect& bounds, | |
791 ui::WindowShowState show_state) { | |
792 WindowBoundsPayload3 payload = { 0 }; | |
793 payload.window_id = window_id.id(); | |
794 payload.x = bounds.x(); | |
795 payload.y = bounds.y(); | |
796 payload.w = bounds.width(); | |
797 payload.h = bounds.height(); | |
798 payload.show_state = ShowStateToPersistedShowState(show_state); | |
799 SessionCommand* command = new SessionCommand(kCommandSetWindowBounds3, | |
800 sizeof(payload)); | |
801 memcpy(command->contents(), &payload, sizeof(payload)); | |
802 return command; | |
803 } | |
804 | |
805 SessionCommand* SessionService::CreateSetTabIndexInWindowCommand( | |
806 const SessionID& tab_id, | |
807 int new_index) { | |
808 TabIndexInWindowPayload payload = { 0 }; | |
809 payload.id = tab_id.id(); | |
810 payload.index = new_index; | |
811 SessionCommand* command = | |
812 new SessionCommand(kCommandSetTabIndexInWindow, sizeof(payload)); | |
813 memcpy(command->contents(), &payload, sizeof(payload)); | |
814 return command; | |
815 } | |
816 | |
817 SessionCommand* SessionService::CreateTabClosedCommand( | |
818 const SessionID::id_type tab_id) { | |
819 ClosedPayload payload; | |
820 // Because of what appears to be a compiler bug setting payload to {0} doesn't | |
821 // set the padding to 0, resulting in Purify reporting an UMR when we write | |
822 // the structure to disk. To avoid this we explicitly memset the struct. | |
823 memset(&payload, 0, sizeof(payload)); | |
824 payload.id = tab_id; | |
825 payload.close_time = Time::Now().ToInternalValue(); | |
826 SessionCommand* command = | |
827 new SessionCommand(kCommandTabClosed, sizeof(payload)); | |
828 memcpy(command->contents(), &payload, sizeof(payload)); | |
829 return command; | |
830 } | |
831 | |
832 SessionCommand* SessionService::CreateWindowClosedCommand( | |
833 const SessionID::id_type window_id) { | |
834 ClosedPayload payload; | |
835 // See comment in CreateTabClosedCommand as to why we do this. | |
836 memset(&payload, 0, sizeof(payload)); | |
837 payload.id = window_id; | |
838 payload.close_time = Time::Now().ToInternalValue(); | |
839 SessionCommand* command = | |
840 new SessionCommand(kCommandWindowClosed, sizeof(payload)); | |
841 memcpy(command->contents(), &payload, sizeof(payload)); | |
842 return command; | |
843 } | |
844 | |
845 SessionCommand* SessionService::CreateSetSelectedNavigationIndexCommand( | |
846 const SessionID& tab_id, | |
847 int index) { | |
848 SelectedNavigationIndexPayload payload = { 0 }; | |
849 payload.id = tab_id.id(); | |
850 payload.index = index; | |
851 SessionCommand* command = new SessionCommand( | |
852 kCommandSetSelectedNavigationIndex, sizeof(payload)); | |
853 memcpy(command->contents(), &payload, sizeof(payload)); | |
854 return command; | |
855 } | |
856 | |
857 SessionCommand* SessionService::CreateSetWindowTypeCommand( | |
858 const SessionID& window_id, | |
859 WindowType type) { | |
860 WindowTypePayload payload = { 0 }; | |
861 payload.id = window_id.id(); | |
862 payload.index = static_cast<int32>(type); | |
863 SessionCommand* command = new SessionCommand( | |
864 kCommandSetWindowType, sizeof(payload)); | |
865 memcpy(command->contents(), &payload, sizeof(payload)); | |
866 return command; | |
867 } | |
868 | |
869 SessionCommand* SessionService::CreatePinnedStateCommand( | |
870 const SessionID& tab_id, | |
871 bool is_pinned) { | |
872 PinnedStatePayload payload = { 0 }; | |
873 payload.tab_id = tab_id.id(); | |
874 payload.pinned_state = is_pinned; | |
875 SessionCommand* command = | |
876 new SessionCommand(kCommandSetPinnedState, sizeof(payload)); | |
877 memcpy(command->contents(), &payload, sizeof(payload)); | |
878 return command; | |
879 } | |
880 | |
881 SessionCommand* SessionService::CreateSessionStorageAssociatedCommand( | |
882 const SessionID& tab_id, | |
883 const std::string& session_storage_persistent_id) { | |
884 Pickle pickle; | |
885 pickle.WriteInt(tab_id.id()); | |
886 pickle.WriteString(session_storage_persistent_id); | |
887 return new SessionCommand(kCommandSessionStorageAssociated, pickle); | |
888 } | |
889 | |
890 SessionCommand* SessionService::CreateSetActiveWindowCommand( | |
891 const SessionID& window_id) { | |
892 ActiveWindowPayload payload = 0; | |
893 payload = window_id.id(); | |
894 SessionCommand* command = | |
895 new SessionCommand(kCommandSetActiveWindow, sizeof(payload)); | |
896 memcpy(command->contents(), &payload, sizeof(payload)); | |
897 return command; | |
898 } | |
899 | |
900 void SessionService::OnGotSessionCommands( | 667 void SessionService::OnGotSessionCommands( |
901 const SessionCallback& callback, | 668 const SessionCallback& callback, |
902 ScopedVector<SessionCommand> commands) { | 669 ScopedVector<SessionCommand> commands) { |
903 ScopedVector<SessionWindow> valid_windows; | 670 ScopedVector<SessionWindow> valid_windows; |
904 SessionID::id_type active_window_id = 0; | 671 SessionID::id_type active_window_id = 0; |
905 | 672 |
673 startup_metric_utils::ScopedSlowStartupUMA | |
674 scoped_timer("Startup.SlowStartupSessionServiceCreateTabsAndWindows"); | |
675 | |
906 RestoreSessionFromCommands( | 676 RestoreSessionFromCommands( |
907 commands.get(), &valid_windows.get(), &active_window_id); | 677 commands.get(), &valid_windows.get(), &active_window_id); |
908 callback.Run(valid_windows.Pass(), active_window_id); | 678 callback.Run(valid_windows.Pass(), active_window_id); |
909 } | 679 } |
910 | 680 |
911 void SessionService::RestoreSessionFromCommands( | |
912 const std::vector<SessionCommand*>& commands, | |
913 std::vector<SessionWindow*>* valid_windows, | |
914 SessionID::id_type* active_window_id) { | |
915 std::map<int, SessionTab*> tabs; | |
916 std::map<int, SessionWindow*> windows; | |
917 | |
918 VLOG(1) << "RestoreSessionFromCommands " << commands.size(); | |
919 if (CreateTabsAndWindows(commands, &tabs, &windows, active_window_id)) { | |
920 AddTabsToWindows(&tabs, &windows); | |
921 SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows); | |
922 UpdateSelectedTabIndex(valid_windows); | |
923 } | |
924 STLDeleteValues(&tabs); | |
925 // Don't delete conents of windows, that is done by the caller as all | |
926 // valid windows are added to valid_windows. | |
927 } | |
928 | |
929 void SessionService::UpdateSelectedTabIndex( | |
930 std::vector<SessionWindow*>* windows) { | |
931 for (std::vector<SessionWindow*>::const_iterator i = windows->begin(); | |
932 i != windows->end(); ++i) { | |
933 // See note in SessionWindow as to why we do this. | |
934 int new_index = 0; | |
935 for (std::vector<SessionTab*>::const_iterator j = (*i)->tabs.begin(); | |
936 j != (*i)->tabs.end(); ++j) { | |
937 if ((*j)->tab_visual_index == (*i)->selected_tab_index) { | |
938 new_index = static_cast<int>(j - (*i)->tabs.begin()); | |
939 break; | |
940 } | |
941 } | |
942 (*i)->selected_tab_index = new_index; | |
943 } | |
944 } | |
945 | |
946 SessionWindow* SessionService::GetWindow( | |
947 SessionID::id_type window_id, | |
948 IdToSessionWindow* windows) { | |
949 std::map<int, SessionWindow*>::iterator i = windows->find(window_id); | |
950 if (i == windows->end()) { | |
951 SessionWindow* window = new SessionWindow(); | |
952 window->window_id.set_id(window_id); | |
953 (*windows)[window_id] = window; | |
954 return window; | |
955 } | |
956 return i->second; | |
957 } | |
958 | |
959 SessionTab* SessionService::GetTab( | |
960 SessionID::id_type tab_id, | |
961 IdToSessionTab* tabs) { | |
962 DCHECK(tabs); | |
963 std::map<int, SessionTab*>::iterator i = tabs->find(tab_id); | |
964 if (i == tabs->end()) { | |
965 SessionTab* tab = new SessionTab(); | |
966 tab->tab_id.set_id(tab_id); | |
967 (*tabs)[tab_id] = tab; | |
968 return tab; | |
969 } | |
970 return i->second; | |
971 } | |
972 | |
973 std::vector<SerializedNavigationEntry>::iterator | |
974 SessionService::FindClosestNavigationWithIndex( | |
975 std::vector<SerializedNavigationEntry>* navigations, | |
976 int index) { | |
977 DCHECK(navigations); | |
978 for (std::vector<SerializedNavigationEntry>::iterator | |
979 i = navigations->begin(); i != navigations->end(); ++i) { | |
980 if (i->index() >= index) | |
981 return i; | |
982 } | |
983 return navigations->end(); | |
984 } | |
985 | |
986 // Function used in sorting windows. Sorting is done based on window id. As | |
987 // window ids increment for each new window, this effectively sorts by creation | |
988 // time. | |
989 static bool WindowOrderSortFunction(const SessionWindow* w1, | |
990 const SessionWindow* w2) { | |
991 return w1->window_id.id() < w2->window_id.id(); | |
992 } | |
993 | |
994 // Compares the two tabs based on visual index. | |
995 static bool TabVisualIndexSortFunction(const SessionTab* t1, | |
996 const SessionTab* t2) { | |
997 const int delta = t1->tab_visual_index - t2->tab_visual_index; | |
998 return delta == 0 ? (t1->tab_id.id() < t2->tab_id.id()) : (delta < 0); | |
999 } | |
1000 | |
1001 void SessionService::SortTabsBasedOnVisualOrderAndPrune( | |
1002 std::map<int, SessionWindow*>* windows, | |
1003 std::vector<SessionWindow*>* valid_windows) { | |
1004 std::map<int, SessionWindow*>::iterator i = windows->begin(); | |
1005 while (i != windows->end()) { | |
1006 SessionWindow* window = i->second; | |
1007 AppType app_type = window->app_name.empty() ? TYPE_NORMAL : TYPE_APP; | |
1008 if (window->tabs.empty() || window->is_constrained || | |
1009 !should_track_changes_for_browser_type( | |
1010 static_cast<Browser::Type>(window->type), | |
1011 app_type)) { | |
1012 delete window; | |
1013 windows->erase(i++); | |
1014 } else { | |
1015 // Valid window; sort the tabs and add it to the list of valid windows. | |
1016 std::sort(window->tabs.begin(), window->tabs.end(), | |
1017 &TabVisualIndexSortFunction); | |
1018 // Otherwise, add the window such that older windows appear first. | |
1019 if (valid_windows->empty()) { | |
1020 valid_windows->push_back(window); | |
1021 } else { | |
1022 valid_windows->insert( | |
1023 std::upper_bound(valid_windows->begin(), valid_windows->end(), | |
1024 window, &WindowOrderSortFunction), | |
1025 window); | |
1026 } | |
1027 ++i; | |
1028 } | |
1029 } | |
1030 } | |
1031 | |
1032 void SessionService::AddTabsToWindows(std::map<int, SessionTab*>* tabs, | |
1033 std::map<int, SessionWindow*>* windows) { | |
1034 VLOG(1) << "AddTabsToWindws"; | |
1035 VLOG(1) << "Tabs " << tabs->size() << ", windows " << windows->size(); | |
1036 std::map<int, SessionTab*>::iterator i = tabs->begin(); | |
1037 while (i != tabs->end()) { | |
1038 SessionTab* tab = i->second; | |
1039 if (tab->window_id.id() && !tab->navigations.empty()) { | |
1040 SessionWindow* window = GetWindow(tab->window_id.id(), windows); | |
1041 window->tabs.push_back(tab); | |
1042 tabs->erase(i++); | |
1043 | |
1044 // See note in SessionTab as to why we do this. | |
1045 std::vector<SerializedNavigationEntry>::iterator j = | |
1046 FindClosestNavigationWithIndex(&(tab->navigations), | |
1047 tab->current_navigation_index); | |
1048 if (j == tab->navigations.end()) { | |
1049 tab->current_navigation_index = | |
1050 static_cast<int>(tab->navigations.size() - 1); | |
1051 } else { | |
1052 tab->current_navigation_index = | |
1053 static_cast<int>(j - tab->navigations.begin()); | |
1054 } | |
1055 } else { | |
1056 // Never got a set tab index in window, or tabs are empty, nothing | |
1057 // to do. | |
1058 ++i; | |
1059 } | |
1060 } | |
1061 } | |
1062 | |
1063 bool SessionService::CreateTabsAndWindows( | |
1064 const std::vector<SessionCommand*>& data, | |
1065 std::map<int, SessionTab*>* tabs, | |
1066 std::map<int, SessionWindow*>* windows, | |
1067 SessionID::id_type* active_window_id) { | |
1068 // If the file is corrupt (command with wrong size, or unknown command), we | |
1069 // still return true and attempt to restore what we we can. | |
1070 VLOG(1) << "CreateTabsAndWindows"; | |
1071 | |
1072 startup_metric_utils::ScopedSlowStartupUMA | |
1073 scoped_timer("Startup.SlowStartupSessionServiceCreateTabsAndWindows"); | |
1074 | |
1075 for (std::vector<SessionCommand*>::const_iterator i = data.begin(); | |
1076 i != data.end(); ++i) { | |
1077 const SessionCommand::id_type kCommandSetWindowBounds2 = 10; | |
1078 const SessionCommand* command = *i; | |
1079 | |
1080 VLOG(1) << "Read command " << (int) command->id(); | |
1081 switch (command->id()) { | |
1082 case kCommandSetTabWindow: { | |
1083 SessionID::id_type payload[2]; | |
1084 if (!command->GetPayload(payload, sizeof(payload))) { | |
1085 VLOG(1) << "Failed reading command " << command->id(); | |
1086 return true; | |
1087 } | |
1088 GetTab(payload[1], tabs)->window_id.set_id(payload[0]); | |
1089 break; | |
1090 } | |
1091 | |
1092 // This is here for forward migration only. New data is saved with | |
1093 // |kCommandSetWindowBounds3|. | |
1094 case kCommandSetWindowBounds2: { | |
1095 WindowBoundsPayload2 payload; | |
1096 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1097 VLOG(1) << "Failed reading command " << command->id(); | |
1098 return true; | |
1099 } | |
1100 GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x, | |
1101 payload.y, | |
1102 payload.w, | |
1103 payload.h); | |
1104 GetWindow(payload.window_id, windows)->show_state = | |
1105 payload.is_maximized ? | |
1106 ui::SHOW_STATE_MAXIMIZED : ui::SHOW_STATE_NORMAL; | |
1107 break; | |
1108 } | |
1109 | |
1110 case kCommandSetWindowBounds3: { | |
1111 WindowBoundsPayload3 payload; | |
1112 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1113 VLOG(1) << "Failed reading command " << command->id(); | |
1114 return true; | |
1115 } | |
1116 GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x, | |
1117 payload.y, | |
1118 payload.w, | |
1119 payload.h); | |
1120 GetWindow(payload.window_id, windows)->show_state = | |
1121 PersistedShowStateToShowState(payload.show_state); | |
1122 break; | |
1123 } | |
1124 | |
1125 case kCommandSetTabIndexInWindow: { | |
1126 TabIndexInWindowPayload payload; | |
1127 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1128 VLOG(1) << "Failed reading command " << command->id(); | |
1129 return true; | |
1130 } | |
1131 GetTab(payload.id, tabs)->tab_visual_index = payload.index; | |
1132 break; | |
1133 } | |
1134 | |
1135 case kCommandTabClosed: | |
1136 case kCommandWindowClosed: { | |
1137 ClosedPayload payload; | |
1138 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1139 VLOG(1) << "Failed reading command " << command->id(); | |
1140 return true; | |
1141 } | |
1142 if (command->id() == kCommandTabClosed) { | |
1143 delete GetTab(payload.id, tabs); | |
1144 tabs->erase(payload.id); | |
1145 } else { | |
1146 delete GetWindow(payload.id, windows); | |
1147 windows->erase(payload.id); | |
1148 } | |
1149 break; | |
1150 } | |
1151 | |
1152 case kCommandTabNavigationPathPrunedFromBack: { | |
1153 TabNavigationPathPrunedFromBackPayload payload; | |
1154 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1155 VLOG(1) << "Failed reading command " << command->id(); | |
1156 return true; | |
1157 } | |
1158 SessionTab* tab = GetTab(payload.id, tabs); | |
1159 tab->navigations.erase( | |
1160 FindClosestNavigationWithIndex(&(tab->navigations), payload.index), | |
1161 tab->navigations.end()); | |
1162 break; | |
1163 } | |
1164 | |
1165 case kCommandTabNavigationPathPrunedFromFront: { | |
1166 TabNavigationPathPrunedFromFrontPayload payload; | |
1167 if (!command->GetPayload(&payload, sizeof(payload)) || | |
1168 payload.index <= 0) { | |
1169 VLOG(1) << "Failed reading command " << command->id(); | |
1170 return true; | |
1171 } | |
1172 SessionTab* tab = GetTab(payload.id, tabs); | |
1173 | |
1174 // Update the selected navigation index. | |
1175 tab->current_navigation_index = | |
1176 std::max(-1, tab->current_navigation_index - payload.index); | |
1177 | |
1178 // And update the index of existing navigations. | |
1179 for (std::vector<SerializedNavigationEntry>::iterator | |
1180 i = tab->navigations.begin(); | |
1181 i != tab->navigations.end();) { | |
1182 i->set_index(i->index() - payload.index); | |
1183 if (i->index() < 0) | |
1184 i = tab->navigations.erase(i); | |
1185 else | |
1186 ++i; | |
1187 } | |
1188 break; | |
1189 } | |
1190 | |
1191 case kCommandUpdateTabNavigation: { | |
1192 SerializedNavigationEntry navigation; | |
1193 SessionID::id_type tab_id; | |
1194 if (!RestoreUpdateTabNavigationCommand( | |
1195 *command, &navigation, &tab_id)) { | |
1196 VLOG(1) << "Failed reading command " << command->id(); | |
1197 return true; | |
1198 } | |
1199 SessionTab* tab = GetTab(tab_id, tabs); | |
1200 std::vector<SerializedNavigationEntry>::iterator i = | |
1201 FindClosestNavigationWithIndex(&(tab->navigations), | |
1202 navigation.index()); | |
1203 if (i != tab->navigations.end() && i->index() == navigation.index()) | |
1204 *i = navigation; | |
1205 else | |
1206 tab->navigations.insert(i, navigation); | |
1207 break; | |
1208 } | |
1209 | |
1210 case kCommandSetSelectedNavigationIndex: { | |
1211 SelectedNavigationIndexPayload payload; | |
1212 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1213 VLOG(1) << "Failed reading command " << command->id(); | |
1214 return true; | |
1215 } | |
1216 GetTab(payload.id, tabs)->current_navigation_index = payload.index; | |
1217 break; | |
1218 } | |
1219 | |
1220 case kCommandSetSelectedTabInIndex: { | |
1221 SelectedTabInIndexPayload payload; | |
1222 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1223 VLOG(1) << "Failed reading command " << command->id(); | |
1224 return true; | |
1225 } | |
1226 GetWindow(payload.id, windows)->selected_tab_index = payload.index; | |
1227 break; | |
1228 } | |
1229 | |
1230 case kCommandSetWindowType: { | |
1231 WindowTypePayload payload; | |
1232 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1233 VLOG(1) << "Failed reading command " << command->id(); | |
1234 return true; | |
1235 } | |
1236 GetWindow(payload.id, windows)->is_constrained = false; | |
1237 GetWindow(payload.id, windows)->type = | |
1238 BrowserTypeForWindowType( | |
1239 static_cast<WindowType>(payload.index)); | |
1240 break; | |
1241 } | |
1242 | |
1243 case kCommandSetPinnedState: { | |
1244 PinnedStatePayload payload; | |
1245 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1246 VLOG(1) << "Failed reading command " << command->id(); | |
1247 return true; | |
1248 } | |
1249 GetTab(payload.tab_id, tabs)->pinned = payload.pinned_state; | |
1250 break; | |
1251 } | |
1252 | |
1253 case kCommandSetWindowAppName: { | |
1254 SessionID::id_type window_id; | |
1255 std::string app_name; | |
1256 if (!RestoreSetWindowAppNameCommand(*command, &window_id, &app_name)) | |
1257 return true; | |
1258 | |
1259 GetWindow(window_id, windows)->app_name.swap(app_name); | |
1260 break; | |
1261 } | |
1262 | |
1263 case kCommandSetExtensionAppID: { | |
1264 SessionID::id_type tab_id; | |
1265 std::string extension_app_id; | |
1266 if (!RestoreSetTabExtensionAppIDCommand( | |
1267 *command, &tab_id, &extension_app_id)) { | |
1268 VLOG(1) << "Failed reading command " << command->id(); | |
1269 return true; | |
1270 } | |
1271 | |
1272 GetTab(tab_id, tabs)->extension_app_id.swap(extension_app_id); | |
1273 break; | |
1274 } | |
1275 | |
1276 case kCommandSetTabUserAgentOverride: { | |
1277 SessionID::id_type tab_id; | |
1278 std::string user_agent_override; | |
1279 if (!RestoreSetTabUserAgentOverrideCommand( | |
1280 *command, &tab_id, &user_agent_override)) { | |
1281 return true; | |
1282 } | |
1283 | |
1284 GetTab(tab_id, tabs)->user_agent_override.swap(user_agent_override); | |
1285 break; | |
1286 } | |
1287 | |
1288 case kCommandSessionStorageAssociated: { | |
1289 scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle()); | |
1290 SessionID::id_type command_tab_id; | |
1291 std::string session_storage_persistent_id; | |
1292 PickleIterator iter(*command_pickle.get()); | |
1293 if (!command_pickle->ReadInt(&iter, &command_tab_id) || | |
1294 !command_pickle->ReadString(&iter, &session_storage_persistent_id)) | |
1295 return true; | |
1296 // Associate the session storage back. | |
1297 GetTab(command_tab_id, tabs)->session_storage_persistent_id = | |
1298 session_storage_persistent_id; | |
1299 break; | |
1300 } | |
1301 | |
1302 case kCommandSetActiveWindow: { | |
1303 ActiveWindowPayload payload; | |
1304 if (!command->GetPayload(&payload, sizeof(payload))) { | |
1305 VLOG(1) << "Failed reading command " << command->id(); | |
1306 return true; | |
1307 } | |
1308 *active_window_id = payload; | |
1309 break; | |
1310 } | |
1311 | |
1312 default: | |
1313 VLOG(1) << "Failed reading an unknown command " << command->id(); | |
1314 return true; | |
1315 } | |
1316 } | |
1317 return true; | |
1318 } | |
1319 | |
1320 void SessionService::BuildCommandsForTab(const SessionID& window_id, | 681 void SessionService::BuildCommandsForTab(const SessionID& window_id, |
1321 WebContents* tab, | 682 WebContents* tab, |
1322 int index_in_window, | 683 int index_in_window, |
1323 bool is_pinned, | 684 bool is_pinned, |
1324 std::vector<SessionCommand*>* commands, | 685 std::vector<SessionCommand*>* commands, |
1325 IdToRange* tab_to_available_range) { | 686 IdToRange* tab_to_available_range) { |
1326 DCHECK(tab && commands && window_id.id()); | 687 DCHECK(tab && commands && window_id.id()); |
1327 SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(tab); | 688 SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(tab); |
1328 const SessionID& session_id(session_tab_helper->session_id()); | 689 const SessionID& session_id(session_tab_helper->session_id()); |
1329 commands->push_back(CreateSetTabWindowCommand(window_id, session_id)); | 690 commands->push_back(CreateSetTabWindowCommand(window_id, session_id)); |
1330 | 691 |
1331 const int current_index = tab->GetController().GetCurrentEntryIndex(); | 692 const int current_index = tab->GetController().GetCurrentEntryIndex(); |
1332 const int min_index = std::max(0, | 693 const int min_index = std::max(0, |
1333 current_index - max_persist_navigation_count); | 694 current_index - max_persist_navigation_count); |
1334 const int max_index = | 695 const int max_index = |
1335 std::min(current_index + max_persist_navigation_count, | 696 std::min(current_index + max_persist_navigation_count, |
1336 tab->GetController().GetEntryCount()); | 697 tab->GetController().GetEntryCount()); |
1337 const int pending_index = tab->GetController().GetPendingEntryIndex(); | 698 const int pending_index = tab->GetController().GetPendingEntryIndex(); |
1338 if (tab_to_available_range) { | 699 if (tab_to_available_range) { |
1339 (*tab_to_available_range)[session_id.id()] = | 700 (*tab_to_available_range)[session_id.id()] = |
1340 std::pair<int, int>(min_index, max_index); | 701 std::pair<int, int>(min_index, max_index); |
1341 } | 702 } |
1342 | 703 |
1343 if (is_pinned) { | 704 if (is_pinned) |
1344 commands->push_back(CreatePinnedStateCommand(session_id, true)); | 705 commands->push_back(CreatePinnedStateCommand(session_id, true)); |
1345 } | |
1346 | 706 |
1347 extensions::TabHelper* extensions_tab_helper = | 707 extensions::TabHelper* extensions_tab_helper = |
1348 extensions::TabHelper::FromWebContents(tab); | 708 extensions::TabHelper::FromWebContents(tab); |
1349 if (extensions_tab_helper->extension_app()) { | 709 if (extensions_tab_helper->extension_app()) { |
1350 commands->push_back( | 710 commands->push_back(CreateSetTabExtensionAppIDCommand( |
1351 CreateSetTabExtensionAppIDCommand( | 711 session_id, |
1352 kCommandSetExtensionAppID, session_id.id(), | 712 extensions_tab_helper->extension_app()->id())); |
1353 extensions_tab_helper->extension_app()->id())); | |
1354 } | 713 } |
1355 | 714 |
1356 const std::string& ua_override = tab->GetUserAgentOverride(); | 715 const std::string& ua_override = tab->GetUserAgentOverride(); |
1357 if (!ua_override.empty()) { | 716 if (!ua_override.empty()) { |
1358 commands->push_back( | 717 commands->push_back(CreateSetTabUserAgentOverrideCommand(session_id, |
1359 CreateSetTabUserAgentOverrideCommand( | 718 ua_override)); |
1360 kCommandSetTabUserAgentOverride, session_id.id(), ua_override)); | |
1361 } | 719 } |
1362 | 720 |
1363 for (int i = min_index; i < max_index; ++i) { | 721 for (int i = min_index; i < max_index; ++i) { |
1364 const NavigationEntry* entry = (i == pending_index) ? | 722 const NavigationEntry* entry = (i == pending_index) ? |
1365 tab->GetController().GetPendingEntry() : | 723 tab->GetController().GetPendingEntry() : |
1366 tab->GetController().GetEntryAtIndex(i); | 724 tab->GetController().GetEntryAtIndex(i); |
1367 DCHECK(entry); | 725 DCHECK(entry); |
1368 if (ShouldTrackEntry(entry->GetVirtualURL())) { | 726 if (ShouldTrackEntry(entry->GetVirtualURL())) { |
1369 const SerializedNavigationEntry navigation = | 727 const SerializedNavigationEntry navigation = |
1370 ContentSerializedNavigationBuilder::FromNavigationEntry(i, *entry); | 728 ContentSerializedNavigationBuilder::FromNavigationEntry(i, *entry); |
1371 commands->push_back( | 729 commands->push_back( |
1372 CreateUpdateTabNavigationCommand( | 730 CreateUpdateTabNavigationCommand(session_id, navigation)); |
1373 kCommandUpdateTabNavigation, session_id.id(), navigation)); | |
1374 } | 731 } |
1375 } | 732 } |
1376 commands->push_back( | 733 commands->push_back( |
1377 CreateSetSelectedNavigationIndexCommand(session_id, current_index)); | 734 CreateSetSelectedNavigationIndexCommand(session_id, current_index)); |
1378 | 735 |
1379 if (index_in_window != -1) { | 736 if (index_in_window != -1) { |
1380 commands->push_back( | 737 commands->push_back( |
1381 CreateSetTabIndexInWindowCommand(session_id, index_in_window)); | 738 CreateSetTabIndexInWindowCommand(session_id, index_in_window)); |
1382 } | 739 } |
1383 | 740 |
(...skipping 12 matching lines...) Expand all Loading... | |
1396 std::set<SessionID::id_type>* windows_to_track) { | 753 std::set<SessionID::id_type>* windows_to_track) { |
1397 DCHECK(browser && commands); | 754 DCHECK(browser && commands); |
1398 DCHECK(browser->session_id().id()); | 755 DCHECK(browser->session_id().id()); |
1399 | 756 |
1400 commands->push_back( | 757 commands->push_back( |
1401 CreateSetWindowBoundsCommand(browser->session_id(), | 758 CreateSetWindowBoundsCommand(browser->session_id(), |
1402 browser->window()->GetRestoredBounds(), | 759 browser->window()->GetRestoredBounds(), |
1403 browser->window()->GetRestoredState())); | 760 browser->window()->GetRestoredState())); |
1404 | 761 |
1405 commands->push_back(CreateSetWindowTypeCommand( | 762 commands->push_back(CreateSetWindowTypeCommand( |
1406 browser->session_id(), WindowTypeForBrowserType(browser->type()))); | 763 browser->session_id(), |
764 WindowTypeForBrowserType(browser->type()))); | |
1407 | 765 |
1408 if (!browser->app_name().empty()) { | 766 if (!browser->app_name().empty()) { |
1409 commands->push_back(CreateSetWindowAppNameCommand( | 767 commands->push_back(CreateSetWindowAppNameCommand(browser->session_id(), |
1410 kCommandSetWindowAppName, | 768 browser->app_name())); |
1411 browser->session_id().id(), | |
1412 browser->app_name())); | |
1413 } | 769 } |
1414 | 770 |
1415 windows_to_track->insert(browser->session_id().id()); | 771 windows_to_track->insert(browser->session_id().id()); |
1416 TabStripModel* tab_strip = browser->tab_strip_model(); | 772 TabStripModel* tab_strip = browser->tab_strip_model(); |
1417 for (int i = 0; i < tab_strip->count(); ++i) { | 773 for (int i = 0; i < tab_strip->count(); ++i) { |
1418 WebContents* tab = tab_strip->GetWebContentsAt(i); | 774 WebContents* tab = tab_strip->GetWebContentsAt(i); |
1419 DCHECK(tab); | 775 DCHECK(tab); |
1420 BuildCommandsForTab(browser->session_id(), tab, i, | 776 BuildCommandsForTab(browser->session_id(), tab, i, |
1421 tab_strip->IsTabPinned(i), | 777 tab_strip->IsTabPinned(i), |
1422 commands, tab_to_available_range); | 778 commands, tab_to_available_range); |
1423 } | 779 } |
1424 | 780 |
1425 commands->push_back( | 781 commands->push_back(CreateSetSelectedTabInWindowCommand( |
1426 CreateSetSelectedTabInWindow(browser->session_id(), | 782 browser->session_id(), |
1427 browser->tab_strip_model()->active_index())); | 783 browser->tab_strip_model()->active_index())); |
1428 } | 784 } |
1429 | 785 |
1430 void SessionService::BuildCommandsFromBrowsers( | 786 void SessionService::BuildCommandsFromBrowsers( |
1431 std::vector<SessionCommand*>* commands, | 787 std::vector<SessionCommand*>* commands, |
1432 IdToRange* tab_to_available_range, | 788 IdToRange* tab_to_available_range, |
1433 std::set<SessionID::id_type>* windows_to_track) { | 789 std::set<SessionID::id_type>* windows_to_track) { |
1434 DCHECK(commands); | 790 DCHECK(commands); |
1435 for (chrome::BrowserIterator it; !it.done(); it.Next()) { | 791 for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
1436 Browser* browser = *it; | 792 Browser* browser = *it; |
1437 // Make sure the browser has tabs and a window. Browser's destructor | 793 // Make sure the browser has tabs and a window. Browser's destructor |
1438 // removes itself from the BrowserList. When a browser is closed the | 794 // removes itself from the BrowserList. When a browser is closed the |
1439 // destructor is not necessarily run immediately. This means it's possible | 795 // destructor is not necessarily run immediately. This means it's possible |
1440 // for us to get a handle to a browser that is about to be removed. If | 796 // for us to get a handle to a browser that is about to be removed. If |
1441 // the tab count is 0 or the window is NULL, the browser is about to be | 797 // the tab count is 0 or the window is NULL, the browser is about to be |
1442 // deleted, so we ignore it. | 798 // deleted, so we ignore it. |
1443 if (ShouldTrackBrowser(browser) && browser->tab_strip_model()->count() && | 799 if (ShouldTrackBrowser(browser) && browser->tab_strip_model()->count() && |
1444 browser->window()) { | 800 browser->window()) { |
1445 BuildCommandsForBrowser(browser, commands, tab_to_available_range, | 801 BuildCommandsForBrowser(browser, commands, tab_to_available_range, |
1446 windows_to_track); | 802 windows_to_track); |
1447 } | 803 } |
1448 } | 804 } |
1449 } | 805 } |
1450 | 806 |
1451 void SessionService::ScheduleReset() { | 807 void SessionService::ScheduleResetCommands() { |
1452 set_pending_reset(true); | 808 set_pending_reset(true); |
1453 STLDeleteElements(&pending_commands()); | 809 STLDeleteElements(&pending_commands()); |
1454 tab_to_available_range_.clear(); | 810 tab_to_available_range_.clear(); |
1455 windows_tracking_.clear(); | 811 windows_tracking_.clear(); |
1456 BuildCommandsFromBrowsers(&pending_commands(), &tab_to_available_range_, | 812 BuildCommandsFromBrowsers(&pending_commands(), &tab_to_available_range_, |
1457 &windows_tracking_); | 813 &windows_tracking_); |
1458 if (!windows_tracking_.empty()) { | 814 if (!windows_tracking_.empty()) { |
1459 // We're lazily created on startup and won't get an initial batch of | 815 // We're lazily created on startup and won't get an initial batch of |
1460 // SetWindowType messages. Set these here to make sure our state is correct. | 816 // SetWindowType messages. Set these here to make sure our state is correct. |
1461 has_open_trackable_browsers_ = true; | 817 has_open_trackable_browsers_ = true; |
1462 move_on_new_browser_ = true; | 818 move_on_new_browser_ = true; |
1463 } | 819 } |
1464 StartSaveTimer(); | 820 StartSaveTimer(); |
1465 } | 821 } |
1466 | 822 |
1467 bool SessionService::ReplacePendingCommand(SessionCommand* command) { | |
1468 // We optimize page navigations, which can happen quite frequently and | |
1469 // are expensive. And activation is like Highlander, there can only be one! | |
1470 if (command->id() != kCommandUpdateTabNavigation && | |
1471 command->id() != kCommandSetActiveWindow) { | |
1472 return false; | |
1473 } | |
1474 for (std::vector<SessionCommand*>::reverse_iterator i = | |
1475 pending_commands().rbegin(); i != pending_commands().rend(); ++i) { | |
1476 SessionCommand* existing_command = *i; | |
1477 if (command->id() == kCommandUpdateTabNavigation && | |
1478 existing_command->id() == kCommandUpdateTabNavigation) { | |
1479 scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle()); | |
1480 PickleIterator iterator(*command_pickle); | |
1481 SessionID::id_type command_tab_id; | |
1482 int command_nav_index; | |
1483 if (!command_pickle->ReadInt(&iterator, &command_tab_id) || | |
1484 !command_pickle->ReadInt(&iterator, &command_nav_index)) { | |
1485 return false; | |
1486 } | |
1487 SessionID::id_type existing_tab_id; | |
1488 int existing_nav_index; | |
1489 { | |
1490 // Creating a pickle like this means the Pickle references the data from | |
1491 // the command. Make sure we delete the pickle before the command, else | |
1492 // the pickle references deleted memory. | |
1493 scoped_ptr<Pickle> existing_pickle(existing_command->PayloadAsPickle()); | |
1494 iterator = PickleIterator(*existing_pickle); | |
1495 if (!existing_pickle->ReadInt(&iterator, &existing_tab_id) || | |
1496 !existing_pickle->ReadInt(&iterator, &existing_nav_index)) { | |
1497 return false; | |
1498 } | |
1499 } | |
1500 if (existing_tab_id == command_tab_id && | |
1501 existing_nav_index == command_nav_index) { | |
1502 // existing_command is an update for the same tab/index pair. Replace | |
1503 // it with the new one. We need to add to the end of the list just in | |
1504 // case there is a prune command after the update command. | |
1505 delete existing_command; | |
1506 pending_commands().erase(i.base() - 1); | |
1507 pending_commands().push_back(command); | |
1508 return true; | |
1509 } | |
1510 return false; | |
1511 } | |
1512 if (command->id() == kCommandSetActiveWindow && | |
1513 existing_command->id() == kCommandSetActiveWindow) { | |
1514 *i = command; | |
1515 delete existing_command; | |
1516 return true; | |
1517 } | |
1518 } | |
1519 return false; | |
1520 } | |
1521 | |
1522 void SessionService::ScheduleCommand(SessionCommand* command) { | 823 void SessionService::ScheduleCommand(SessionCommand* command) { |
1523 DCHECK(command); | 824 DCHECK(command); |
1524 if (ReplacePendingCommand(command)) | 825 if (ReplacePendingCommand(command, pending_commands())) |
1525 return; | 826 return; |
1526 BaseSessionService::ScheduleCommand(command); | 827 BaseSessionService::ScheduleCommand(command); |
1527 // Don't schedule a reset on tab closed/window closed. Otherwise we may | 828 // Don't schedule a reset on tab closed/window closed. Otherwise we may |
1528 // lose tabs/windows we want to restore from if we exit right after this. | 829 // lose tabs/windows we want to restore from if we exit right after this. |
1529 if (!pending_reset() && pending_window_close_ids_.empty() && | 830 if (!pending_reset() && pending_window_close_ids_.empty() && |
1530 commands_since_reset() >= kWritesPerReset && | 831 commands_since_reset() >= kWritesPerReset && !IsClosingCommand(command)) { |
1531 (command->id() != kCommandTabClosed && | 832 ScheduleResetCommands(); |
1532 command->id() != kCommandWindowClosed)) { | |
1533 ScheduleReset(); | |
1534 } | 833 } |
1535 } | 834 } |
1536 | 835 |
1537 void SessionService::CommitPendingCloses() { | 836 void SessionService::CommitPendingCloses() { |
1538 for (PendingTabCloseIDs::iterator i = pending_tab_close_ids_.begin(); | 837 for (PendingTabCloseIDs::iterator i = pending_tab_close_ids_.begin(); |
1539 i != pending_tab_close_ids_.end(); ++i) { | 838 i != pending_tab_close_ids_.end(); ++i) { |
1540 ScheduleCommand(CreateTabClosedCommand(*i)); | 839 ScheduleCommand(CreateTabClosedCommand(*i)); |
1541 } | 840 } |
1542 pending_tab_close_ids_.clear(); | 841 pending_tab_close_ids_.clear(); |
1543 | 842 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1598 bool SessionService::ShouldTrackBrowser(Browser* browser) const { | 897 bool SessionService::ShouldTrackBrowser(Browser* browser) const { |
1599 if (browser->profile() != profile()) | 898 if (browser->profile() != profile()) |
1600 return false; | 899 return false; |
1601 // Never track app popup windows that do not have a trusted source (i.e. | 900 // Never track app popup windows that do not have a trusted source (i.e. |
1602 // popup windows spawned by an app). If this logic changes, be sure to also | 901 // popup windows spawned by an app). If this logic changes, be sure to also |
1603 // change SessionRestoreImpl::CreateRestoredBrowser(). | 902 // change SessionRestoreImpl::CreateRestoredBrowser(). |
1604 if (browser->is_app() && browser->is_type_popup() && | 903 if (browser->is_app() && browser->is_type_popup() && |
1605 !browser->is_trusted_source()) { | 904 !browser->is_trusted_source()) { |
1606 return false; | 905 return false; |
1607 } | 906 } |
1608 AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL; | 907 SessionServiceCommands::AppType app_type = |
1609 return should_track_changes_for_browser_type(browser->type(), app_type); | 908 browser->is_app() ? SessionServiceCommands::TYPE_APP : |
1610 } | 909 SessionServiceCommands::TYPE_NORMAL; |
1611 | 910 return ShouldRestoreWindowOfType(WindowTypeForBrowserType(browser->type()), |
1612 bool SessionService::should_track_changes_for_browser_type(Browser::Type type, | 911 app_type); |
1613 AppType app_type) { | |
1614 #if defined(OS_CHROMEOS) | |
1615 // Restore app popups for chromeos alone. | |
1616 if (type == Browser::TYPE_POPUP && app_type == TYPE_APP) | |
1617 return true; | |
1618 #endif | |
1619 | |
1620 return type == Browser::TYPE_TABBED; | |
1621 } | |
1622 | |
1623 SessionService::WindowType SessionService::WindowTypeForBrowserType( | |
1624 Browser::Type type) { | |
1625 switch (type) { | |
1626 case Browser::TYPE_POPUP: | |
1627 return TYPE_POPUP; | |
1628 case Browser::TYPE_TABBED: | |
1629 return TYPE_TABBED; | |
1630 default: | |
1631 DCHECK(false); | |
1632 return TYPE_TABBED; | |
1633 } | |
1634 } | |
1635 | |
1636 Browser::Type SessionService::BrowserTypeForWindowType(WindowType type) { | |
1637 switch (type) { | |
1638 case TYPE_POPUP: | |
1639 return Browser::TYPE_POPUP; | |
1640 case TYPE_TABBED: | |
1641 default: | |
1642 return Browser::TYPE_TABBED; | |
1643 } | |
1644 } | 912 } |
1645 | 913 |
1646 void SessionService::RecordSessionUpdateHistogramData(int type, | 914 void SessionService::RecordSessionUpdateHistogramData(int type, |
1647 base::TimeTicks* last_updated_time) { | 915 base::TimeTicks* last_updated_time) { |
1648 if (!last_updated_time->is_null()) { | 916 if (!last_updated_time->is_null()) { |
1649 base::TimeDelta delta = base::TimeTicks::Now() - *last_updated_time; | 917 base::TimeDelta delta = base::TimeTicks::Now() - *last_updated_time; |
1650 // We're interested in frequent updates periods longer than | 918 // We're interested in frequent updates periods longer than |
1651 // 10 minutes. | 919 // 10 minutes. |
1652 bool use_long_period = false; | 920 bool use_long_period = false; |
1653 if (delta >= save_delay_in_mins_) { | 921 if (delta >= save_delay_in_mins_) { |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1766 if (use_long_period) { | 1034 if (use_long_period) { |
1767 std::string long_name_("SessionRestore.SaveLongPeriod"); | 1035 std::string long_name_("SessionRestore.SaveLongPeriod"); |
1768 UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, | 1036 UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, |
1769 delta, | 1037 delta, |
1770 save_delay_in_mins_, | 1038 save_delay_in_mins_, |
1771 save_delay_in_hrs_, | 1039 save_delay_in_hrs_, |
1772 50); | 1040 50); |
1773 } | 1041 } |
1774 } | 1042 } |
1775 | 1043 |
1776 void SessionService::TabInserted(WebContents* contents) { | |
1777 SessionTabHelper* session_tab_helper = | |
1778 SessionTabHelper::FromWebContents(contents); | |
1779 if (!ShouldTrackChangesToWindow(session_tab_helper->window_id())) | |
1780 return; | |
1781 SetTabWindow(session_tab_helper->window_id(), | |
1782 session_tab_helper->session_id()); | |
1783 extensions::TabHelper* extensions_tab_helper = | |
1784 extensions::TabHelper::FromWebContents(contents); | |
1785 if (extensions_tab_helper && | |
1786 extensions_tab_helper->extension_app()) { | |
1787 SetTabExtensionAppID( | |
1788 session_tab_helper->window_id(), | |
1789 session_tab_helper->session_id(), | |
1790 extensions_tab_helper->extension_app()->id()); | |
1791 } | |
1792 | |
1793 // Record the association between the SessionStorageNamespace and the | |
1794 // tab. | |
1795 // | |
1796 // TODO(ajwong): This should be processing the whole map rather than | |
1797 // just the default. This in particular will not work for tabs with only | |
1798 // isolated apps which won't have a default partition. | |
1799 content::SessionStorageNamespace* session_storage_namespace = | |
1800 contents->GetController().GetDefaultSessionStorageNamespace(); | |
1801 ScheduleCommand(CreateSessionStorageAssociatedCommand( | |
1802 session_tab_helper->session_id(), | |
1803 session_storage_namespace->persistent_id())); | |
1804 session_storage_namespace->SetShouldPersist(true); | |
1805 } | |
1806 | |
1807 void SessionService::TabClosing(WebContents* contents) { | |
1808 // Allow the associated sessionStorage to get deleted; it won't be needed | |
1809 // in the session restore. | |
1810 content::SessionStorageNamespace* session_storage_namespace = | |
1811 contents->GetController().GetDefaultSessionStorageNamespace(); | |
1812 session_storage_namespace->SetShouldPersist(false); | |
1813 SessionTabHelper* session_tab_helper = | |
1814 SessionTabHelper::FromWebContents(contents); | |
1815 TabClosed(session_tab_helper->window_id(), | |
1816 session_tab_helper->session_id(), | |
1817 contents->GetClosedByUserGesture()); | |
1818 RecordSessionUpdateHistogramData(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
1819 &last_updated_tab_closed_time_); | |
1820 } | |
1821 | |
1822 void SessionService::MaybeDeleteSessionOnlyData() { | 1044 void SessionService::MaybeDeleteSessionOnlyData() { |
1823 // Don't try anything if we're testing. The browser_process is not fully | 1045 // Don't try anything if we're testing. The browser_process is not fully |
1824 // created and DeleteSession will crash if we actually attempt it. | 1046 // created and DeleteSession will crash if we actually attempt it. |
1825 if (!profile() || profile()->AsTestingProfile()) | 1047 if (!profile() || profile()->AsTestingProfile()) |
1826 return; | 1048 return; |
1827 | 1049 |
1828 // Clear session data if the last window for a profile has been closed and | 1050 // Clear session data if the last window for a profile has been closed and |
1829 // closing the last window would normally close Chrome, unless background mode | 1051 // closing the last window would normally close Chrome, unless background mode |
1830 // is active. Tests don't have a background_mode_manager. | 1052 // is active. Tests don't have a background_mode_manager. |
1831 if (has_open_trackable_browsers_ || | 1053 if (has_open_trackable_browsers_ || |
1832 browser_defaults::kBrowserAliveWithNoWindows || | 1054 browser_defaults::kBrowserAliveWithNoWindows || |
1833 g_browser_process->background_mode_manager()->IsBackgroundModeActive()) { | 1055 g_browser_process->background_mode_manager()->IsBackgroundModeActive()) { |
1834 return; | 1056 return; |
1835 } | 1057 } |
1836 | 1058 |
1837 // Check for any open windows for the current profile that we aren't tracking. | 1059 // Check for any open windows for the current profile that we aren't tracking. |
1838 for (chrome::BrowserIterator it; !it.done(); it.Next()) { | 1060 for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
1839 if ((*it)->profile() == profile()) | 1061 if ((*it)->profile() == profile()) |
1840 return; | 1062 return; |
1841 } | 1063 } |
1842 DeleteSessionOnlyData(profile()); | 1064 DeleteSessionOnlyData(profile()); |
1843 } | 1065 } |
OLD | NEW |