session_service.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/background/background_mode_manager.h"
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/browser_process.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/defaults.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/session_startup_pref.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/browser/profiles/profile_manager.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_backend.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_command.h"
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/sessions/session_data_deleter.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_restore.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_tab_helper.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_types.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_tabstrip.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/startup/startup_browser_creator.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "components/startup_metric_utils/startup_metric_utils.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_details.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/session_storage_namespace.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/app_controller_mac.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using sessions::SerializedNavigationEntry;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Identifier for commands written to file.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetTabWindow = 0;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OBSOLETE Superseded by kCommandSetWindowBounds3.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static const SessionCommand::id_type kCommandSetWindowBounds = 1;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetTabIndexInWindow = 2;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Original kCommandTabClosed/kCommandWindowClosed. See comment in
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MigrateClosedPayload for details on why they were replaced.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandTabClosedObsolete = 3;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandWindowClosedObsolete = 4;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kCommandTabNavigationPathPrunedFromBack = 5;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandUpdateTabNavigation = 6;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetSelectedNavigationIndex = 7;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetSelectedTabInIndex = 8;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetWindowType = 9;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OBSOLETE Superseded by kCommandSetWindowBounds3. Except for data migration.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kCommandTabNavigationPathPrunedFromFront = 11;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetPinnedState = 12;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetExtensionAppID = 13;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetWindowBounds3 = 14;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetWindowAppName = 15;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandTabClosed = 16;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandWindowClosed = 17;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetTabUserAgentOverride = 18;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSessionStorageAssociated = 19;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetActiveWindow = 20;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Every kWritesPerReset commands triggers recreating the file.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kWritesPerReset = 250;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Various payload structures.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ClosedPayload {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type id;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 close_time;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WindowBoundsPayload2 {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type window_id;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 x;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 y;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 w;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 h;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_maximized;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WindowBoundsPayload3 {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type window_id;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 x;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 y;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 w;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 h;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 show_state;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SessionID::id_type ActiveWindowPayload;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IDAndIndexPayload {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type id;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 index;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload TabIndexInWindowPayload;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload TabNavigationPathPrunedFromBackPayload;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload SelectedNavigationIndexPayload;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload SelectedTabInIndexPayload;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload WindowTypePayload;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload TabNavigationPathPrunedFromFrontPayload;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PinnedStatePayload {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type tab_id;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pinned_state;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Persisted versions of ui::WindowShowState that are written to disk and can
14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// never change.
14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)enum PersistedWindowShowState {
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // SHOW_STATE_DEFAULT (0) never persisted.
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PERSISTED_SHOW_STATE_NORMAL = 1,
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PERSISTED_SHOW_STATE_MINIMIZED = 2,
14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PERSISTED_SHOW_STATE_MAXIMIZED = 3,
14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // SHOW_STATE_INACTIVE (4) never persisted.
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PERSISTED_SHOW_STATE_FULLSCREEN = 5,
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PERSISTED_SHOW_STATE_DETACHED_DEPRECATED = 6,
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PERSISTED_SHOW_STATE_END = 6
15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Assert to ensure PersistedWindowShowState is updated if ui::WindowShowState
15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// is changed.
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)COMPILE_ASSERT(ui::SHOW_STATE_END ==
15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                   static_cast<ui::WindowShowState>(PERSISTED_SHOW_STATE_END),
15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)               persisted_show_state_mismatch);
15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the show state to store to disk based |state|.
16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)PersistedWindowShowState ShowStateToPersistedShowState(
16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ui::WindowShowState state) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_NORMAL:
16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return PERSISTED_SHOW_STATE_NORMAL;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_MINIMIZED:
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return PERSISTED_SHOW_STATE_MINIMIZED;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_MAXIMIZED:
16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return PERSISTED_SHOW_STATE_MAXIMIZED;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_FULLSCREEN:
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return PERSISTED_SHOW_STATE_FULLSCREEN;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_DEFAULT:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_INACTIVE:
17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return PERSISTED_SHOW_STATE_NORMAL;
17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_END:
17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      break;
17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  NOTREACHED();
18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return PERSISTED_SHOW_STATE_NORMAL;
18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Lints show state values when read back from persited disk.
18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)ui::WindowShowState PersistedShowStateToShowState(int state) {
18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  switch (state) {
18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case PERSISTED_SHOW_STATE_NORMAL:
18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return ui::SHOW_STATE_NORMAL;
18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case PERSISTED_SHOW_STATE_MINIMIZED:
18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return ui::SHOW_STATE_MINIMIZED;
19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case PERSISTED_SHOW_STATE_MAXIMIZED:
19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return ui::SHOW_STATE_MAXIMIZED;
19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case PERSISTED_SHOW_STATE_FULLSCREEN:
19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return ui::SHOW_STATE_FULLSCREEN;
19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case PERSISTED_SHOW_STATE_DETACHED_DEPRECATED:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ui::SHOW_STATE_NORMAL;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  NOTREACHED();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui::SHOW_STATE_NORMAL;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Migrates a |ClosedPayload|, returning true on success (migration was
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// necessary and happened), or false (migration was not necessary or was not
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// successful).
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MigrateClosedPayload(const SessionCommand& command,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          ClosedPayload* payload) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pre M17 versions of chromeos were 32bit. Post M17 is 64 bit. Apparently the
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 32 bit versions of chrome on pre M17 resulted in a sizeof 12 for the
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ClosedPayload, where as post M17 64-bit gives a sizeof 16 (presumably the
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // struct is padded).
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((command.id() == kCommandWindowClosedObsolete ||
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       command.id() == kCommandTabClosedObsolete) &&
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command.size() == 12 && sizeof(payload->id) == 4 &&
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sizeof(payload->close_time) == 8) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&payload->id, command.contents(), 4);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&payload->close_time, command.contents() + 4, 8);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SessionService -------------------------------------------------------------
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionService::SessionService(Profile* profile)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : BaseSessionService(SESSION_RESTORE, profile, base::FilePath()),
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_open_trackable_browsers_(false),
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      move_on_new_browser_(false),
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)),
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_(base::TimeDelta::FromMinutes(10)),
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_hrs_(base::TimeDelta::FromHours(8)),
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      force_browser_not_alive_with_no_windows_(false),
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_factory_(this) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SessionService::SessionService(const base::FilePath& save_path)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : BaseSessionService(SESSION_RESTORE, NULL, save_path),
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_open_trackable_browsers_(false),
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      move_on_new_browser_(false),
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)),
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_(base::TimeDelta::FromMinutes(10)),
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_hrs_(base::TimeDelta::FromHours(8)),
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      force_browser_not_alive_with_no_windows_(false),
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_factory_(this) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionService::~SessionService() {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The BrowserList should outlive the SessionService since it's static and
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // the SessionService is a KeyedService.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserList::RemoveObserver(this);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Save();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RestoreIfNecessary(urls_to_open, NULL);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::ResetFromCurrentBrowsers() {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleReset();
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::MoveCurrentSessionToLastSession() {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tab_close_ids_.clear();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_closing_ids_.clear();
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_window_close_ids_.clear();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Save();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTaskOnBackendThread(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&SessionBackend::MoveCurrentSessionToLastSession,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            backend()));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetTabWindow(const SessionID& window_id,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const SessionID& tab_id) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabWindowCommand(window_id, tab_id));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetWindowBounds(const SessionID& window_id,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const gfx::Rect& bounds,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     ui::WindowShowState show_state) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetWindowBoundsCommand(window_id, bounds, show_state));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetTabIndexInWindow(const SessionID& window_id,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SessionID& tab_id,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int new_index) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabIndexInWindowCommand(tab_id, new_index));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetPinnedState(const SessionID& window_id,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const SessionID& tab_id,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool is_pinned) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreatePinnedStateCommand(tab_id, is_pinned));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabClosed(const SessionID& window_id,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const SessionID& tab_id,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               bool closed_by_user_gesture) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tab_id.id())
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Hapens when the tab is replaced.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdToRange::iterator i = tab_to_available_range_.find(tab_id.id());
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != tab_to_available_range_.end())
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab_to_available_range_.erase(i);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (find(pending_window_close_ids_.begin(), pending_window_close_ids_.end(),
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           window_id.id()) != pending_window_close_ids_.end()) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tab is in last window. Don't commit it immediately, instead add it to the
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // list of tabs to close. If the user creates another window, the close is
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // committed.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_tab_close_ids_.insert(tab_id.id());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (find(window_closing_ids_.begin(), window_closing_ids_.end(),
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  window_id.id()) != window_closing_ids_.end() ||
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             !IsOnlyOneTabLeft() ||
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             closed_by_user_gesture) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Close is the result of one of the following:
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // . window close (and it isn't the last window).
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // . closing a tab and there are other windows/tabs open.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // . closed by a user gesture.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In all cases we need to mark the tab as explicitly closed.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateTabClosedCommand(tab_id.id()));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // User closed the last tab in the last tabbed browser. Don't mark the
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // tab closed.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_tab_close_ids_.insert(tab_id.id());
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_open_trackable_browsers_ = false;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SessionService::WindowOpened(Browser* browser) {
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!ShouldTrackBrowser(browser))
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL;
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RestoreIfNecessary(std::vector<GURL>(), browser);
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SetWindowType(browser->session_id(), browser->type(), app_type);
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SetWindowAppName(browser->session_id(), browser->app_name());
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::WindowClosing(const SessionID& window_id) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The window is about to close. If there are other tabbed browsers with the
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same original profile commit the close immediately.
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: if the user chooses the exit menu item session service is destroyed
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and this code isn't hit.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_open_trackable_browsers_) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Closing a window can never make has_open_trackable_browsers_ go from
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // false to true, so only update it if already true.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_open_trackable_browsers_ = HasOpenTrackableBrowsers(window_id);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
377e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  bool use_pending_close = !has_open_trackable_browsers_;
378e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!use_pending_close) {
379e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Somewhat outside of "normal behavior" is profile locking.  In this case
380e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // (when IsSiginRequired has already been set True), we're closing all
381e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // browser windows in turn but want them all to be restored when the user
382e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // unlocks.  To accomplish this, we do a "pending close" on all windows
383e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // instead of just the last one (which has no open_trackable_browsers).
384e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // http://crbug.com/356818
385e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    //
386e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Some editions (like iOS) don't have a profile_manager and some tests
387e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // don't supply one so be lenient.
388e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (g_browser_process) {
389e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ProfileManager* profile_manager = g_browser_process->profile_manager();
390e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (profile_manager) {
391e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        ProfileInfoCache& profile_info =
392e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            profile_manager->GetProfileInfoCache();
393e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        size_t profile_index = profile_info.GetIndexOfProfileWithPath(
394e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            profile()->GetPath());
395e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        use_pending_close = profile_index != std::string::npos &&
396e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            profile_info.ProfileIsSigninRequiredAtIndex(profile_index);
397e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      }
398e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
399e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
400e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (use_pending_close)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_window_close_ids_.insert(window_id.id());
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_closing_ids_.insert(window_id.id());
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::WindowClosed(const SessionID& window_id) {
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id)) {
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // The last window may be one that is not tracked.
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MaybeDeleteSessionOnlyData();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windows_tracking_.erase(window_id.id());
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_closing_ids_.find(window_id.id()) != window_closing_ids_.end()) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_closing_ids_.erase(window_id.id());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateWindowClosedCommand(window_id.id()));
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (pending_window_close_ids_.find(window_id.id()) ==
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             pending_window_close_ids_.end()) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We'll hit this if user closed the last tab in a window.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_open_trackable_browsers_ = HasOpenTrackableBrowsers(window_id);
42223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (!has_open_trackable_browsers_)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_window_close_ids_.insert(window_id.id());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScheduleCommand(CreateWindowClosedCommand(window_id.id()));
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MaybeDeleteSessionOnlyData();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetWindowType(const SessionID& window_id,
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   Browser::Type type,
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   AppType app_type) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!should_track_changes_for_browser_type(type, app_type))
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windows_tracking_.insert(window_id.id());
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The user created a new tabbed browser with our profile. Commit any
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending closes.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommitPendingCloses();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_open_trackable_browsers_ = true;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  move_on_new_browser_ = true;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateSetWindowTypeCommand(window_id, WindowTypeForBrowserType(type)));
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetWindowAppName(
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& app_name) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabExtensionAppIDCommand(
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      kCommandSetWindowAppName,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      window_id.id(),
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      app_name));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabNavigationPathPrunedFromBack(const SessionID& window_id,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     const SessionID& tab_id,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     int count) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabNavigationPathPrunedFromBackPayload payload = { 0 };
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id.id();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = count;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandTabNavigationPathPrunedFromBack,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         sizeof(payload));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(command);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabNavigationPathPrunedFromFront(
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int count) {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the range of indices.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab_to_available_range_.find(tab_id.id()) !=
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_to_available_range_.end()) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::pair<int, int>& range = tab_to_available_range_[tab_id.id()];
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range.first = std::max(0, range.first - count);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range.second = std::max(0, range.second - count);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabNavigationPathPrunedFromFrontPayload payload = { 0 };
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id.id();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = count;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandTabNavigationPathPrunedFromFront,
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         sizeof(payload));
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(command);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::UpdateTabNavigation(
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const SerializedNavigationEntry& navigation) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackEntry(navigation.virtual_url()) ||
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !ShouldTrackChangesToWindow(window_id)) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab_to_available_range_.find(tab_id.id()) !=
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_to_available_range_.end()) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::pair<int, int>& range = tab_to_available_range_[tab_id.id()];
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range.first = std::min(navigation.index(), range.first);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range.second = std::max(navigation.index(), range.second);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation,
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   tab_id.id(), navigation));
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SessionService::TabRestored(WebContents* tab, bool pinned) {
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(tab);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(session_tab_helper->window_id()))
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BuildCommandsForTab(session_tab_helper->window_id(), tab, -1,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      pinned, &pending_commands(), NULL);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartSaveTimer();
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetSelectedNavigationIndex(const SessionID& window_id,
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                const SessionID& tab_id,
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                int index) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab_to_available_range_.find(tab_id.id()) !=
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_to_available_range_.end()) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index < tab_to_available_range_[tab_id.id()].first ||
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        index > tab_to_available_range_[tab_id.id()].second) {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The new index is outside the range of what we've archived, schedule
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // a reset.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResetFromCurrentBrowsers();
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetSelectedNavigationIndexCommand(tab_id, index));
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetSelectedTabInWindow(const SessionID& window_id,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int index) {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetSelectedTabInWindow(window_id, index));
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetTabUserAgentOverride(
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_agent_override) {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabUserAgentOverrideCommand(
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kCommandSetTabUserAgentOverride, tab_id.id(), user_agent_override));
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId SessionService::GetLastSession(
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SessionCallback& callback,
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // OnGotSessionCommands maps the SessionCommands to browser state, then run
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the callback.
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ScheduleGetLastSessionCommands(
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SessionService::OnGotSessionCommands,
5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 weak_factory_.GetWeakPtr(), callback),
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tracker);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::Save() {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool had_commands = !pending_commands().empty();
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseSessionService::Save();
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (had_commands) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RecordSessionUpdateHistogramData(chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &last_updated_save_time_);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NotificationService::current()->Notify(
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Profile>(profile()),
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NotificationService::NoDetails());
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::Init() {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register for the notifications we're interested in.
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_NAV_LIST_PRUNED,
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_CHANGED,
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources());
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserList::AddObserver(this);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SessionService::processed_any_commands() {
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return backend()->inited() || !pending_commands().empty();
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::ShouldNewWindowStartSession() {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChromeOS and OSX have different ideas of application lifetime than
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the other platforms.
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On ChromeOS opening a new window should never start a new session.
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!force_browser_not_alive_with_no_windows_)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_open_trackable_browsers_ &&
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !StartupBrowserCreator::InSynchronousProfileLaunch() &&
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !SessionRestore::IsRestoring(profile())
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // On OSX, a new window should not start a new session if it was opened
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // from the dock or the menubar.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && !app_controller_mac::IsOpeningNewWindow()
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_MACOSX
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        Browser* browser) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldNewWindowStartSession()) {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're going from no tabbed browsers to a tabbed browser (and not in
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // process startup), restore the last session.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (move_on_new_browser_) {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make the current session the last.
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MoveCurrentSessionToLastSession();
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      move_on_new_browser_ = false;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionStartupPref pref = StartupBrowserCreator::GetSessionStartupPref(
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *CommandLine::ForCurrentProcess(), profile());
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pref.type == SessionStartupPref::LAST) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionRestore::RestoreSession(
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          profile(), browser,
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          browser ? browser->host_desktop_type() : chrome::GetActiveDesktop(),
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          browser ? 0 : SessionRestore::ALWAYS_CREATE_TABBED_BROWSER,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          urls_to_open);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::Observe(int type,
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationSource& source,
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationDetails& details) {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All of our messages have the NavigationController as the source.
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_NAV_LIST_PRUNED: {
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebContents* web_contents =
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::NavigationController>(source).ptr()->
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetWebContents();
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper* session_tab_helper =
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SessionTabHelper::FromWebContents(web_contents);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!session_tab_helper || web_contents->GetBrowserContext() != profile())
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<content::PrunedDetails> pruned_details(details);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pruned_details->from_front) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabNavigationPathPrunedFromFront(
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->window_id(),
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->session_id(),
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pruned_details->count);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabNavigationPathPrunedFromBack(
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->window_id(),
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->session_id(),
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            web_contents->GetController().GetEntryCount());
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RecordSessionUpdateHistogramData(type,
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       &last_updated_nav_list_pruned_time_);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_NAV_ENTRY_CHANGED: {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebContents* web_contents =
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::NavigationController>(source).ptr()->
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetWebContents();
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper* session_tab_helper =
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SessionTabHelper::FromWebContents(web_contents);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!session_tab_helper || web_contents->GetBrowserContext() != profile())
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<content::EntryChangedDetails> changed(details);
697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const SerializedNavigationEntry navigation =
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SerializedNavigationEntry::FromNavigationEntry(
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              changed->index, *changed->changed_entry);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateTabNavigation(session_tab_helper->window_id(),
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          session_tab_helper->session_id(),
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          navigation);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_NAV_ENTRY_COMMITTED: {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebContents* web_contents =
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::NavigationController>(source).ptr()->
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetWebContents();
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper* session_tab_helper =
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SessionTabHelper::FromWebContents(web_contents);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!session_tab_helper || web_contents->GetBrowserContext() != profile())
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int current_entry_index =
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          web_contents->GetController().GetCurrentEntryIndex();
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetSelectedNavigationIndex(
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_tab_helper->window_id(),
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_tab_helper->session_id(),
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          current_entry_index);
720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const SerializedNavigationEntry navigation =
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SerializedNavigationEntry::FromNavigationEntry(
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              current_entry_index,
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              *web_contents->GetController().GetEntryAtIndex(
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  current_entry_index));
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateTabNavigation(
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_tab_helper->window_id(),
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_tab_helper->session_id(),
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          navigation);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<content::LoadCommittedDetails> changed(details);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (changed->type == content::NAVIGATION_TYPE_NEW_PAGE ||
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        changed->type == content::NAVIGATION_TYPE_EXISTING_PAGE) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordSessionUpdateHistogramData(type,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &last_updated_nav_entry_commit_time_);
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED: {
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions::TabHelper* extension_tab_helper =
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<extensions::TabHelper>(source).ptr();
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (extension_tab_helper->web_contents()->GetBrowserContext() !=
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              profile()) {
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (extension_tab_helper->extension_app()) {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionTabHelper* session_tab_helper =
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            SessionTabHelper::FromWebContents(
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                extension_tab_helper->web_contents());
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetTabExtensionAppID(session_tab_helper->window_id(),
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             session_tab_helper->session_id(),
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             extension_tab_helper->extension_app()->id());
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::OnBrowserSetLastActive(Browser* browser) {
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldTrackBrowser(browser))
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateSetActiveWindowCommand(browser->session_id()));
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetTabExtensionAppID(
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_app_id) {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID,
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_id.id(), extension_app_id));
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetSelectedTabInWindow(
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index) {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectedTabInIndexPayload payload = { 0 };
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = window_id.id();
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = index;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command = new SessionCommand(kCommandSetSelectedTabInIndex,
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 sizeof(payload));
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetTabWindowCommand(
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id) {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type payload[] = { window_id.id(), tab_id.id() };
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandSetTabWindow, sizeof(payload));
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), payload, sizeof(payload));
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetWindowBoundsCommand(
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& bounds,
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::WindowShowState show_state) {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowBoundsPayload3 payload = { 0 };
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.window_id = window_id.id();
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.x = bounds.x();
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.y = bounds.y();
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.w = bounds.width();
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.h = bounds.height();
80903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  payload.show_state = ShowStateToPersistedShowState(show_state);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command = new SessionCommand(kCommandSetWindowBounds3,
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               sizeof(payload));
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetTabIndexInWindowCommand(
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int new_index) {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabIndexInWindowPayload payload = { 0 };
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id.id();
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = new_index;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandSetTabIndexInWindow, sizeof(payload));
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateTabClosedCommand(
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID::id_type tab_id) {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClosedPayload payload;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Because of what appears to be a compiler bug setting payload to {0} doesn't
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set the padding to 0, resulting in Purify reporting an UMR when we write
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the structure to disk. To avoid this we explicitly memset the struct.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&payload, 0, sizeof(payload));
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.close_time = Time::Now().ToInternalValue();
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandTabClosed, sizeof(payload));
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateWindowClosedCommand(
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID::id_type window_id) {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClosedPayload payload;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See comment in CreateTabClosedCommand as to why we do this.
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&payload, 0, sizeof(payload));
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = window_id;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.close_time = Time::Now().ToInternalValue();
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandWindowClosed, sizeof(payload));
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetSelectedNavigationIndexCommand(
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index) {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectedNavigationIndexPayload payload = { 0 };
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id.id();
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = index;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command = new SessionCommand(
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kCommandSetSelectedNavigationIndex, sizeof(payload));
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetWindowTypeCommand(
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WindowType type) {
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowTypePayload payload = { 0 };
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = window_id.id();
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = static_cast<int32>(type);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command = new SessionCommand(
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kCommandSetWindowType, sizeof(payload));
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreatePinnedStateCommand(
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_pinned) {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PinnedStatePayload payload = { 0 };
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.tab_id = tab_id.id();
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.pinned_state = is_pinned;
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandSetPinnedState, sizeof(payload));
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSessionStorageAssociatedCommand(
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& session_storage_persistent_id) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pickle pickle;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pickle.WriteInt(tab_id.id());
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pickle.WriteString(session_storage_persistent_id);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new SessionCommand(kCommandSessionStorageAssociated, pickle);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetActiveWindowCommand(
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveWindowPayload payload = 0;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload = window_id.id();
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandSetActiveWindow, sizeof(payload));
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::OnGotSessionCommands(
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SessionCallback& callback,
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScopedVector<SessionCommand> commands) {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<SessionWindow> valid_windows;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type active_window_id = 0;
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestoreSessionFromCommands(
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      commands.get(), &valid_windows.get(), &active_window_id);
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(valid_windows.Pass(), active_window_id);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RestoreSessionFromCommands(
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<SessionCommand*>& commands,
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionWindow*>* valid_windows,
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type* active_window_id) {
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionTab*> tabs;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionWindow*> windows;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "RestoreSessionFromCommands " << commands.size();
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CreateTabsAndWindows(commands, &tabs, &windows, active_window_id)) {
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddTabsToWindows(&tabs, &windows);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateSelectedTabIndex(valid_windows);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteValues(&tabs);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't delete conents of windows, that is done by the caller as all
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // valid windows are added to valid_windows.
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::UpdateSelectedTabIndex(
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionWindow*>* windows) {
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<SessionWindow*>::const_iterator i = windows->begin();
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != windows->end(); ++i) {
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See note in SessionWindow as to why we do this.
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int new_index = 0;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<SessionTab*>::const_iterator j = (*i)->tabs.begin();
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         j != (*i)->tabs.end(); ++j) {
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*j)->tab_visual_index == (*i)->selected_tab_index) {
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_index = static_cast<int>(j - (*i)->tabs.begin());
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*i)->selected_tab_index = new_index;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionWindow* SessionService::GetWindow(
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type window_id,
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdToSessionWindow* windows) {
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionWindow*>::iterator i = windows->find(window_id);
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == windows->end()) {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionWindow* window = new SessionWindow();
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->window_id.set_id(window_id);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*windows)[window_id] = window;
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return window;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return i->second;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionTab* SessionService::GetTab(
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type tab_id,
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdToSessionTab* tabs) {
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(tabs);
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionTab*>::iterator i = tabs->find(tab_id);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == tabs->end()) {
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionTab* tab = new SessionTab();
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab->tab_id.set_id(tab_id);
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*tabs)[tab_id] = tab;
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return tab;
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return i->second;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
984c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::vector<SerializedNavigationEntry>::iterator
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionService::FindClosestNavigationWithIndex(
986c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<SerializedNavigationEntry>* navigations,
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index) {
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(navigations);
989c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (std::vector<SerializedNavigationEntry>::iterator
990c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           i = navigations->begin(); i != navigations->end(); ++i) {
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->index() >= index)
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return navigations->end();
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Function used in sorting windows. Sorting is done based on window id. As
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// window ids increment for each new window, this effectively sorts by creation
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time.
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool WindowOrderSortFunction(const SessionWindow* w1,
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const SessionWindow* w2) {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return w1->window_id.id() < w2->window_id.id();
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Compares the two tabs based on visual index.
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool TabVisualIndexSortFunction(const SessionTab* t1,
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const SessionTab* t2) {
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int delta = t1->tab_visual_index - t2->tab_visual_index;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return delta == 0 ? (t1->tab_id.id() < t2->tab_id.id()) : (delta < 0);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SortTabsBasedOnVisualOrderAndPrune(
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<int, SessionWindow*>* windows,
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionWindow*>* valid_windows) {
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionWindow*>::iterator i = windows->begin();
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (i != windows->end()) {
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionWindow* window = i->second;
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppType app_type = window->app_name.empty() ? TYPE_NORMAL : TYPE_APP;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window->tabs.empty() || window->is_constrained ||
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !should_track_changes_for_browser_type(
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<Browser::Type>(window->type),
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            app_type)) {
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete window;
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windows->erase(i++);
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Valid window; sort the tabs and add it to the list of valid windows.
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::sort(window->tabs.begin(), window->tabs.end(),
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &TabVisualIndexSortFunction);
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Otherwise, add the window such that older windows appear first.
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (valid_windows->empty()) {
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        valid_windows->push_back(window);
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        valid_windows->insert(
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            std::upper_bound(valid_windows->begin(), valid_windows->end(),
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             window, &WindowOrderSortFunction),
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            window);
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::AddTabsToWindows(std::map<int, SessionTab*>* tabs,
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::map<int, SessionWindow*>* windows) {
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "AddTabsToWindws";
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Tabs " << tabs->size() << ", windows " << windows->size();
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionTab*>::iterator i = tabs->begin();
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (i != tabs->end()) {
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionTab* tab = i->second;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tab->window_id.id() && !tab->navigations.empty()) {
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionWindow* window = GetWindow(tab->window_id.id(), windows);
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window->tabs.push_back(tab);
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tabs->erase(i++);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See note in SessionTab as to why we do this.
1056c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::vector<SerializedNavigationEntry>::iterator j =
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FindClosestNavigationWithIndex(&(tab->navigations),
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         tab->current_navigation_index);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (j == tab->navigations.end()) {
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tab->current_navigation_index =
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<int>(tab->navigations.size() - 1);
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tab->current_navigation_index =
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<int>(j - tab->navigations.begin());
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Never got a set tab index in window, or tabs are empty, nothing
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to do.
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::CreateTabsAndWindows(
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<SessionCommand*>& data,
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<int, SessionTab*>* tabs,
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<int, SessionWindow*>* windows,
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type* active_window_id) {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the file is corrupt (command with wrong size, or unknown command), we
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // still return true and attempt to restore what we we can.
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CreateTabsAndWindows";
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  startup_metric_utils::ScopedSlowStartupUMA
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_timer("Startup.SlowStartupSessionServiceCreateTabsAndWindows");
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<SessionCommand*>::const_iterator i = data.begin();
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != data.end(); ++i) {
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionCommand* command = *i;
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Read command " << (int) command->id();
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (command->id()) {
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetTabWindow: {
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type payload[2];
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(payload, sizeof(payload))) {
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(payload[1], tabs)->window_id.set_id(payload[0]);
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is here for forward migration only.  New data is saved with
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |kCommandSetWindowBounds3|.
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetWindowBounds2: {
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WindowBoundsPayload2 payload;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x,
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.y,
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.w,
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.h);
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.window_id, windows)->show_state =
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            payload.is_maximized ?
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ui::SHOW_STATE_MAXIMIZED : ui::SHOW_STATE_NORMAL;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetWindowBounds3: {
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WindowBoundsPayload3 payload;
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x,
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.y,
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.w,
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.h);
113103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        GetWindow(payload.window_id, windows)->show_state =
113203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            PersistedShowStateToShowState(payload.show_state);
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetTabIndexInWindow: {
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabIndexInWindowPayload payload;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(payload.id, tabs)->tab_visual_index = payload.index;
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandTabClosedObsolete:
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandWindowClosedObsolete:
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandTabClosed:
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandWindowClosed: {
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ClosedPayload payload;
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload)) &&
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !MigrateClosedPayload(*command, &payload)) {
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (command->id() == kCommandTabClosed ||
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            command->id() == kCommandTabClosedObsolete) {
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delete GetTab(payload.id, tabs);
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tabs->erase(payload.id);
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delete GetWindow(payload.id, windows);
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          windows->erase(payload.id);
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandTabNavigationPathPrunedFromBack: {
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabNavigationPathPrunedFromBackPayload payload;
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionTab* tab = GetTab(payload.id, tabs);
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tab->navigations.erase(
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FindClosestNavigationWithIndex(&(tab->navigations), payload.index),
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tab->navigations.end());
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandTabNavigationPathPrunedFromFront: {
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabNavigationPathPrunedFromFrontPayload payload;
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload)) ||
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            payload.index <= 0) {
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionTab* tab = GetTab(payload.id, tabs);
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Update the selected navigation index.
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tab->current_navigation_index =
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            std::max(-1, tab->current_navigation_index - payload.index);
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // And update the index of existing navigations.
1194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        for (std::vector<SerializedNavigationEntry>::iterator
1195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 i = tab->navigations.begin();
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             i != tab->navigations.end();) {
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          i->set_index(i->index() - payload.index);
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (i->index() < 0)
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            i = tab->navigations.erase(i);
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          else
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ++i;
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandUpdateTabNavigation: {
1207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        SerializedNavigationEntry navigation;
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type tab_id;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!RestoreUpdateTabNavigationCommand(
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *command, &navigation, &tab_id)) {
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionTab* tab = GetTab(tab_id, tabs);
1215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        std::vector<SerializedNavigationEntry>::iterator i =
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FindClosestNavigationWithIndex(&(tab->navigations),
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           navigation.index());
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (i != tab->navigations.end() && i->index() == navigation.index())
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *i = navigation;
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tab->navigations.insert(i, navigation);
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetSelectedNavigationIndex: {
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SelectedNavigationIndexPayload payload;
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(payload.id, tabs)->current_navigation_index = payload.index;
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetSelectedTabInIndex: {
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SelectedTabInIndexPayload payload;
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.id, windows)->selected_tab_index = payload.index;
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetWindowType: {
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WindowTypePayload payload;
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.id, windows)->is_constrained = false;
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.id, windows)->type =
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            BrowserTypeForWindowType(
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                static_cast<WindowType>(payload.index));
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetPinnedState: {
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PinnedStatePayload payload;
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(payload.tab_id, tabs)->pinned = payload.pinned_state;
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetWindowAppName: {
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type window_id;
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string app_name;
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!RestoreSetWindowAppNameCommand(*command, &window_id, &app_name))
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(window_id, windows)->app_name.swap(app_name);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetExtensionAppID: {
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type tab_id;
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string extension_app_id;
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!RestoreSetTabExtensionAppIDCommand(
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *command, &tab_id, &extension_app_id)) {
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(tab_id, tabs)->extension_app_id.swap(extension_app_id);
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetTabUserAgentOverride: {
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type tab_id;
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string user_agent_override;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!RestoreSetTabUserAgentOverrideCommand(
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *command, &tab_id, &user_agent_override)) {
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(tab_id, tabs)->user_agent_override.swap(user_agent_override);
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSessionStorageAssociated: {
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle());
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type command_tab_id;
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string session_storage_persistent_id;
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PickleIterator iter(*command_pickle.get());
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command_pickle->ReadInt(&iter, &command_tab_id) ||
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !command_pickle->ReadString(&iter, &session_storage_persistent_id))
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Associate the session storage back.
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(command_tab_id, tabs)->session_storage_persistent_id =
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_storage_persistent_id;
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetActiveWindow: {
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ActiveWindowPayload payload;
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *active_window_id = payload;
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VLOG(1) << "Failed reading an unknown command " << command->id();
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SessionService::BuildCommandsForTab(const SessionID& window_id,
13362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         WebContents* tab,
13372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int index_in_window,
13382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         bool is_pinned,
13392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         std::vector<SessionCommand*>* commands,
13402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         IdToRange* tab_to_available_range) {
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(tab && commands && window_id.id());
13422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(tab);
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SessionID& session_id(session_tab_helper->session_id());
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(CreateSetTabWindowCommand(window_id, session_id));
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int current_index = tab->GetController().GetCurrentEntryIndex();
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int min_index = std::max(0,
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 current_index - max_persist_navigation_count);
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int max_index =
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::min(current_index + max_persist_navigation_count,
13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               tab->GetController().GetEntryCount());
13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int pending_index = tab->GetController().GetPendingEntryIndex();
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab_to_available_range) {
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*tab_to_available_range)[session_id.id()] =
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::pair<int, int>(min_index, max_index);
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_pinned) {
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(CreatePinnedStateCommand(session_id, true));
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::TabHelper* extensions_tab_helper =
13632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::TabHelper::FromWebContents(tab);
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extensions_tab_helper->extension_app()) {
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateSetTabExtensionAppIDCommand(
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            kCommandSetExtensionAppID, session_id.id(),
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            extensions_tab_helper->extension_app()->id()));
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& ua_override = tab->GetUserAgentOverride();
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ua_override.empty()) {
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateSetTabUserAgentOverrideCommand(
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            kCommandSetTabUserAgentOverride, session_id.id(), ua_override));
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = min_index; i < max_index; ++i) {
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const NavigationEntry* entry = (i == pending_index) ?
13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tab->GetController().GetPendingEntry() :
13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tab->GetController().GetEntryAtIndex(i);
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(entry);
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ShouldTrackEntry(entry->GetVirtualURL())) {
1384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const SerializedNavigationEntry navigation =
1385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SerializedNavigationEntry::FromNavigationEntry(i, *entry);
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      commands->push_back(
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateUpdateTabNavigationCommand(
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kCommandUpdateTabNavigation, session_id.id(), navigation));
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateSetSelectedNavigationIndexCommand(session_id, current_index));
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index_in_window != -1) {
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateSetTabIndexInWindowCommand(session_id, index_in_window));
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record the association between the sessionStorage namespace and the tab.
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::SessionStorageNamespace* session_storage_namespace =
1401ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      tab->GetController().GetDefaultSessionStorageNamespace();
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSessionStorageAssociatedCommand(
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_tab_helper->session_id(),
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_storage_namespace->persistent_id()));
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::BuildCommandsForBrowser(
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser,
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionCommand*>* commands,
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdToRange* tab_to_available_range,
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<SessionID::id_type>* windows_to_track) {
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(browser && commands);
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(browser->session_id().id());
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateSetWindowBoundsCommand(browser->session_id(),
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   browser->window()->GetRestoredBounds(),
1418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                   browser->window()->GetRestoredState()));
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(CreateSetWindowTypeCommand(
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser->session_id(), WindowTypeForBrowserType(browser->type())));
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!browser->app_name().empty()) {
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(CreateSetWindowAppNameCommand(
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kCommandSetWindowAppName,
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->session_id().id(),
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->app_name()));
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  windows_to_track->insert(browser->session_id().id());
14312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TabStripModel* tab_strip = browser->tab_strip_model();
14322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < tab_strip->count(); ++i) {
14332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebContents* tab = tab_strip->GetWebContentsAt(i);
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(tab);
14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BuildCommandsForTab(browser->session_id(), tab, i,
14362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        tab_strip->IsTabPinned(i),
14372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        commands, tab_to_available_range);
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateSetSelectedTabInWindow(browser->session_id(),
14422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   browser->tab_strip_model()->active_index()));
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::BuildCommandsFromBrowsers(
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionCommand*>* commands,
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdToRange* tab_to_available_range,
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<SessionID::id_type>* windows_to_track) {
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(commands);
14502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
14512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = *it;
14522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Make sure the browser has tabs and a window. Browser's destructor
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // removes itself from the BrowserList. When a browser is closed the
14542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // destructor is not necessarily run immediately. This means it's possible
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for us to get a handle to a browser that is about to be removed. If
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the tab count is 0 or the window is NULL, the browser is about to be
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // deleted, so we ignore it.
14582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ShouldTrackBrowser(browser) && browser->tab_strip_model()->count() &&
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->window()) {
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BuildCommandsForBrowser(browser, commands, tab_to_available_range,
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              windows_to_track);
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::ScheduleReset() {
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_pending_reset(true);
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&pending_commands());
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tab_to_available_range_.clear();
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windows_tracking_.clear();
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BuildCommandsFromBrowsers(&pending_commands(), &tab_to_available_range_,
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &windows_tracking_);
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!windows_tracking_.empty()) {
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're lazily created on startup and won't get an initial batch of
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SetWindowType messages. Set these here to make sure our state is correct.
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_open_trackable_browsers_ = true;
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    move_on_new_browser_ = true;
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartSaveTimer();
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::ReplacePendingCommand(SessionCommand* command) {
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We optimize page navigations, which can happen quite frequently and
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are expensive. And activation is like Highlander, there can only be one!
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command->id() != kCommandUpdateTabNavigation &&
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command->id() != kCommandSetActiveWindow) {
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<SessionCommand*>::reverse_iterator i =
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       pending_commands().rbegin(); i != pending_commands().rend(); ++i) {
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionCommand* existing_command = *i;
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (command->id() == kCommandUpdateTabNavigation &&
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        existing_command->id() == kCommandUpdateTabNavigation) {
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle());
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PickleIterator iterator(*command_pickle);
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionID::id_type command_tab_id;
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int command_nav_index;
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!command_pickle->ReadInt(&iterator, &command_tab_id) ||
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !command_pickle->ReadInt(&iterator, &command_nav_index)) {
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionID::id_type existing_tab_id;
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int existing_nav_index;
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Creating a pickle like this means the Pickle references the data from
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the command. Make sure we delete the pickle before the command, else
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the pickle references deleted memory.
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_ptr<Pickle> existing_pickle(existing_command->PayloadAsPickle());
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iterator = PickleIterator(*existing_pickle);
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!existing_pickle->ReadInt(&iterator, &existing_tab_id) ||
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !existing_pickle->ReadInt(&iterator, &existing_nav_index)) {
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (existing_tab_id == command_tab_id &&
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          existing_nav_index == command_nav_index) {
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // existing_command is an update for the same tab/index pair. Replace
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // it with the new one. We need to add to the end of the list just in
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // case there is a prune command after the update command.
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete existing_command;
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_commands().erase(i.base() - 1);
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_commands().push_back(command);
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (command->id() == kCommandSetActiveWindow &&
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        existing_command->id() == kCommandSetActiveWindow) {
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *i = command;
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete existing_command;
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::ScheduleCommand(SessionCommand* command) {
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(command);
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ReplacePendingCommand(command))
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseSessionService::ScheduleCommand(command);
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't schedule a reset on tab closed/window closed. Otherwise we may
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lose tabs/windows we want to restore from if we exit right after this.
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pending_reset() && pending_window_close_ids_.empty() &&
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      commands_since_reset() >= kWritesPerReset &&
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (command->id() != kCommandTabClosed &&
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       command->id() != kCommandWindowClosed)) {
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleReset();
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::CommitPendingCloses() {
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingTabCloseIDs::iterator i = pending_tab_close_ids_.begin();
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_tab_close_ids_.end(); ++i) {
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateTabClosedCommand(*i));
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tab_close_ids_.clear();
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingWindowCloseIDs::iterator i = pending_window_close_ids_.begin();
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_window_close_ids_.end(); ++i) {
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateWindowClosedCommand(*i));
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_window_close_ids_.clear();
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::IsOnlyOneTabLeft() const {
1567e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!profile() || profile()->AsTestingProfile()) {
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're testing, always return false.
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int window_count = 0;
15732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
15742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = *it;
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID::id_type window_id = browser->session_id().id();
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ShouldTrackBrowser(browser) &&
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window_closing_ids_.find(window_id) == window_closing_ids_.end()) {
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (++window_count > 1)
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // By the time this is invoked the tab has been removed. As such, we use
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // > 0 here rather than > 1.
15822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (browser->tab_strip_model()->count() > 0)
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::HasOpenTrackableBrowsers(
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id) const {
1591e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!profile() || profile()->AsTestingProfile()) {
1592e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // We're testing, always return true.
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
15972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = *it;
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID::id_type browser_id = browser->session_id().id();
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (browser_id != window_id.id() &&
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window_closing_ids_.find(browser_id) == window_closing_ids_.end() &&
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ShouldTrackBrowser(browser)) {
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::ShouldTrackChangesToWindow(
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id) const {
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return windows_tracking_.find(window_id.id()) != windows_tracking_.end();
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::ShouldTrackBrowser(Browser* browser) const {
1614a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (browser->profile() != profile())
1615a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return false;
1616a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Never track app popup windows that do not have a trusted source (i.e.
1617a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // popup windows spawned by an app). If this logic changes, be sure to also
1618a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // change SessionRestoreImpl::CreateRestoredBrowser().
1619a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (browser->is_app() && browser->is_type_popup() &&
1620a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      !browser->is_trusted_source()) {
1621a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return false;
1622a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL;
1624a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return should_track_changes_for_browser_type(browser->type(), app_type);
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::should_track_changes_for_browser_type(Browser::Type type,
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           AppType app_type) {
16292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
16302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Restore app popups for chromeos alone.
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == Browser::TYPE_POPUP && app_type == TYPE_APP)
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return type == Browser::TYPE_TABBED;
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionService::WindowType SessionService::WindowTypeForBrowserType(
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser::Type type) {
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Browser::TYPE_POPUP:
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TYPE_POPUP;
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Browser::TYPE_TABBED:
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TYPE_TABBED;
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(false);
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TYPE_TABBED;
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Browser::Type SessionService::BrowserTypeForWindowType(WindowType type) {
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_POPUP:
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Browser::TYPE_POPUP;
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_TABBED:
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Browser::TYPE_TABBED;
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordSessionUpdateHistogramData(int type,
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeTicks* last_updated_time) {
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!last_updated_time->is_null()) {
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta delta = base::TimeTicks::Now() - *last_updated_time;
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're interested in frequent updates periods longer than
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 10 minutes.
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool use_long_period = false;
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delta >= save_delay_in_mins_) {
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_long_period = true;
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (type) {
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case chrome::NOTIFICATION_SESSION_SERVICE_SAVED :
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSaveTime(delta, use_long_period);
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSessionNavigationOrTab(delta, use_long_period);
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case content::NOTIFICATION_WEB_CONTENTS_DESTROYED:
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedTabClosed(delta, use_long_period);
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSessionNavigationOrTab(delta, use_long_period);
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case content::NOTIFICATION_NAV_LIST_PRUNED:
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedNavListPruned(delta, use_long_period);
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSessionNavigationOrTab(delta, use_long_period);
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case content::NOTIFICATION_NAV_ENTRY_COMMITTED:
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedNavEntryCommit(delta, use_long_period);
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSessionNavigationOrTab(delta, use_long_period);
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "Bad type sent to RecordSessionUpdateHistogramData";
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*last_updated_time) = base::TimeTicks::Now();
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedTabClosed(base::TimeDelta delta,
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            bool use_long_period) {
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.TabClosedPeriod");
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.TabClosedLongPeriod");
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedNavListPruned(base::TimeDelta delta,
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                bool use_long_period) {
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.NavigationListPrunedPeriod");
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.NavigationListPrunedLongPeriod");
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedNavEntryCommit(base::TimeDelta delta,
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 bool use_long_period) {
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.NavEntryCommittedPeriod");
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.NavEntryCommittedLongPeriod");
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedSessionNavigationOrTab(base::TimeDelta delta,
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                         bool use_long_period) {
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.NavOrTabUpdatePeriod");
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.NavOrTabUpdateLongPeriod");
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedSaveTime(base::TimeDelta delta,
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool use_long_period) {
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.SavePeriod");
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.SaveLongPeriod");
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabInserted(WebContents* contents) {
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionTabHelper* session_tab_helper =
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper::FromWebContents(contents);
17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ShouldTrackChangesToWindow(session_tab_helper->window_id()))
17952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetTabWindow(session_tab_helper->window_id(),
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               session_tab_helper->session_id());
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::TabHelper* extensions_tab_helper =
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions::TabHelper::FromWebContents(contents);
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extensions_tab_helper &&
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions_tab_helper->extension_app()) {
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetTabExtensionAppID(
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_tab_helper->window_id(),
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_tab_helper->session_id(),
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions_tab_helper->extension_app()->id());
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record the association between the SessionStorageNamespace and the
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tab.
1810ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  //
1811ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // TODO(ajwong): This should be processing the whole map rather than
1812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // just the default. This in particular will not work for tabs with only
1813ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // isolated apps which won't have a default partition.
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::SessionStorageNamespace* session_storage_namespace =
1815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      contents->GetController().GetDefaultSessionStorageNamespace();
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSessionStorageAssociatedCommand(
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_tab_helper->session_id(),
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_storage_namespace->persistent_id()));
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_storage_namespace->SetShouldPersist(true);
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabClosing(WebContents* contents) {
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow the associated sessionStorage to get deleted; it won't be needed
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the session restore.
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::SessionStorageNamespace* session_storage_namespace =
1826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      contents->GetController().GetDefaultSessionStorageNamespace();
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_storage_namespace->SetShouldPersist(false);
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionTabHelper* session_tab_helper =
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper::FromWebContents(contents);
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabClosed(session_tab_helper->window_id(),
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->session_id(),
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            contents->GetClosedByUserGesture());
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecordSessionUpdateHistogramData(content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &last_updated_tab_closed_time_);
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SessionService::MaybeDeleteSessionOnlyData() {
1838e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Don't try anything if we're testing.  The browser_process is not fully
1839e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // created and DeleteSession will crash if we actually attempt it.
1840e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!profile() || profile()->AsTestingProfile())
1841e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return;
1842e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
18435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Clear session data if the last window for a profile has been closed and
18445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // closing the last window would normally close Chrome, unless background mode
1845e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // is active.  Tests don't have a background_mode_manager.
18465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (has_open_trackable_browsers_ ||
18475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      browser_defaults::kBrowserAliveWithNoWindows ||
18485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_browser_process->background_mode_manager()->IsBackgroundModeActive()) {
18495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
18505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
18515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check for any open windows for the current profile that we aren't tracking.
18535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
18545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if ((*it)->profile() == profile())
18555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
18565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
18575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeleteSessionOnlyData(profile());
18585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1859