session_service.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/session_startup_pref.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_backend.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_command.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_restore.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_tab_helper.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_types.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_tabstrip.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/startup/startup_browser_creator.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/startup_metric_utils.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_details.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/session_storage_namespace.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/app_controller_mac.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using sessions::SerializedNavigationEntry;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Identifier for commands written to file.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetTabWindow = 0;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OBSOLETE Superseded by kCommandSetWindowBounds3.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static const SessionCommand::id_type kCommandSetWindowBounds = 1;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetTabIndexInWindow = 2;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Original kCommandTabClosed/kCommandWindowClosed. See comment in
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MigrateClosedPayload for details on why they were replaced.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandTabClosedObsolete = 3;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandWindowClosedObsolete = 4;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kCommandTabNavigationPathPrunedFromBack = 5;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandUpdateTabNavigation = 6;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetSelectedNavigationIndex = 7;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetSelectedTabInIndex = 8;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetWindowType = 9;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OBSOLETE Superseded by kCommandSetWindowBounds3. Except for data migration.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kCommandTabNavigationPathPrunedFromFront = 11;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetPinnedState = 12;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetExtensionAppID = 13;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetWindowBounds3 = 14;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetWindowAppName = 15;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandTabClosed = 16;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandWindowClosed = 17;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetTabUserAgentOverride = 18;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSessionStorageAssociated = 19;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SessionCommand::id_type kCommandSetActiveWindow = 20;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Every kWritesPerReset commands triggers recreating the file.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kWritesPerReset = 250;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Various payload structures.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ClosedPayload {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type id;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 close_time;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WindowBoundsPayload2 {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type window_id;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 x;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 y;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 w;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 h;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_maximized;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WindowBoundsPayload3 {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type window_id;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 x;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 y;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 w;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 h;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 show_state;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SessionID::id_type ActiveWindowPayload;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IDAndIndexPayload {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type id;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 index;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload TabIndexInWindowPayload;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload TabNavigationPathPrunedFromBackPayload;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload SelectedNavigationIndexPayload;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload SelectedTabInIndexPayload;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload WindowTypePayload;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IDAndIndexPayload TabNavigationPathPrunedFromFrontPayload;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PinnedStatePayload {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type tab_id;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pinned_state;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the show state to store to disk based |state|.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::WindowShowState AdjustShowState(ui::WindowShowState state) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_NORMAL:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_MINIMIZED:
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_MAXIMIZED:
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_FULLSCREEN:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return state;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_DEFAULT:
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_INACTIVE:
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::SHOW_STATE_END:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ui::SHOW_STATE_NORMAL;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui::SHOW_STATE_NORMAL;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Migrates a |ClosedPayload|, returning true on success (migration was
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// necessary and happened), or false (migration was not necessary or was not
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// successful).
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MigrateClosedPayload(const SessionCommand& command,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          ClosedPayload* payload) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pre M17 versions of chromeos were 32bit. Post M17 is 64 bit. Apparently the
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 32 bit versions of chrome on pre M17 resulted in a sizeof 12 for the
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ClosedPayload, where as post M17 64-bit gives a sizeof 16 (presumably the
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // struct is padded).
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((command.id() == kCommandWindowClosedObsolete ||
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       command.id() == kCommandTabClosedObsolete) &&
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command.size() == 12 && sizeof(payload->id) == 4 &&
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sizeof(payload->close_time) == 8) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&payload->id, command.contents(), 4);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&payload->close_time, command.contents() + 4, 8);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SessionService -------------------------------------------------------------
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionService::SessionService(Profile* profile)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : BaseSessionService(SESSION_RESTORE, profile, base::FilePath()),
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_open_trackable_browsers_(false),
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      move_on_new_browser_(false),
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)),
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_(base::TimeDelta::FromMinutes(10)),
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_hrs_(base::TimeDelta::FromHours(8)),
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      force_browser_not_alive_with_no_windows_(false) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SessionService::SessionService(const base::FilePath& save_path)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : BaseSessionService(SESSION_RESTORE, NULL, save_path),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_open_trackable_browsers_(false),
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      move_on_new_browser_(false),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)),
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_(base::TimeDelta::FromMinutes(10)),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_hrs_(base::TimeDelta::FromHours(8)),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      force_browser_not_alive_with_no_windows_(false)  {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionService::~SessionService() {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The BrowserList should outlive the SessionService since it's static and
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the SessionService is a ProfileKeyedService.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserList::RemoveObserver(this);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Save();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RestoreIfNecessary(urls_to_open, NULL);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::ResetFromCurrentBrowsers() {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleReset();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::MoveCurrentSessionToLastSession() {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tab_close_ids_.clear();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_closing_ids_.clear();
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_window_close_ids_.clear();
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Save();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTaskOnBackendThread(
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&SessionBackend::MoveCurrentSessionToLastSession,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            backend()));
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetTabWindow(const SessionID& window_id,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const SessionID& tab_id) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabWindowCommand(window_id, tab_id));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetWindowBounds(const SessionID& window_id,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const gfx::Rect& bounds,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     ui::WindowShowState show_state) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetWindowBoundsCommand(window_id, bounds, show_state));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetTabIndexInWindow(const SessionID& window_id,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SessionID& tab_id,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int new_index) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabIndexInWindowCommand(tab_id, new_index));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetPinnedState(const SessionID& window_id,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const SessionID& tab_id,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool is_pinned) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreatePinnedStateCommand(tab_id, is_pinned));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabClosed(const SessionID& window_id,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const SessionID& tab_id,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               bool closed_by_user_gesture) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tab_id.id())
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Hapens when the tab is replaced.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdToRange::iterator i = tab_to_available_range_.find(tab_id.id());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != tab_to_available_range_.end())
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab_to_available_range_.erase(i);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (find(pending_window_close_ids_.begin(), pending_window_close_ids_.end(),
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           window_id.id()) != pending_window_close_ids_.end()) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tab is in last window. Don't commit it immediately, instead add it to the
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // list of tabs to close. If the user creates another window, the close is
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // committed.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_tab_close_ids_.insert(tab_id.id());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (find(window_closing_ids_.begin(), window_closing_ids_.end(),
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  window_id.id()) != window_closing_ids_.end() ||
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             !IsOnlyOneTabLeft() ||
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             closed_by_user_gesture) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Close is the result of one of the following:
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // . window close (and it isn't the last window).
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // . closing a tab and there are other windows/tabs open.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // . closed by a user gesture.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In all cases we need to mark the tab as explicitly closed.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateTabClosedCommand(tab_id.id()));
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // User closed the last tab in the last tabbed browser. Don't mark the
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // tab closed.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_tab_close_ids_.insert(tab_id.id());
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_open_trackable_browsers_ = false;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::WindowClosing(const SessionID& window_id) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The window is about to close. If there are other tabbed browsers with the
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same original profile commit the close immediately.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: if the user chooses the exit menu item session service is destroyed
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and this code isn't hit.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_open_trackable_browsers_) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Closing a window can never make has_open_trackable_browsers_ go from
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // false to true, so only update it if already true.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_open_trackable_browsers_ = HasOpenTrackableBrowsers(window_id);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_record_close_as_pending())
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_window_close_ids_.insert(window_id.id());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_closing_ids_.insert(window_id.id());
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::WindowClosed(const SessionID& window_id) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windows_tracking_.erase(window_id.id());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_closing_ids_.find(window_id.id()) != window_closing_ids_.end()) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_closing_ids_.erase(window_id.id());
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateWindowClosedCommand(window_id.id()));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (pending_window_close_ids_.find(window_id.id()) ==
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             pending_window_close_ids_.end()) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We'll hit this if user closed the last tab in a window.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_open_trackable_browsers_ = HasOpenTrackableBrowsers(window_id);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (should_record_close_as_pending())
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_window_close_ids_.insert(window_id.id());
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScheduleCommand(CreateWindowClosedCommand(window_id.id()));
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetWindowType(const SessionID& window_id,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   Browser::Type type,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   AppType app_type) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!should_track_changes_for_browser_type(type, app_type))
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windows_tracking_.insert(window_id.id());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The user created a new tabbed browser with our profile. Commit any
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending closes.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommitPendingCloses();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_open_trackable_browsers_ = true;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  move_on_new_browser_ = true;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateSetWindowTypeCommand(window_id, WindowTypeForBrowserType(type)));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetWindowAppName(
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& app_name) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabExtensionAppIDCommand(
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      kCommandSetWindowAppName,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      window_id.id(),
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      app_name));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabNavigationPathPrunedFromBack(const SessionID& window_id,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     const SessionID& tab_id,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     int count) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabNavigationPathPrunedFromBackPayload payload = { 0 };
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id.id();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = count;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandTabNavigationPathPrunedFromBack,
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         sizeof(payload));
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(command);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabNavigationPathPrunedFromFront(
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int count) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the range of indices.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab_to_available_range_.find(tab_id.id()) !=
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_to_available_range_.end()) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::pair<int, int>& range = tab_to_available_range_[tab_id.id()];
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range.first = std::max(0, range.first - count);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range.second = std::max(0, range.second - count);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabNavigationPathPrunedFromFrontPayload payload = { 0 };
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id.id();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = count;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandTabNavigationPathPrunedFromFront,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         sizeof(payload));
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(command);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::UpdateTabNavigation(
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const SerializedNavigationEntry& navigation) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackEntry(navigation.virtual_url()) ||
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !ShouldTrackChangesToWindow(window_id)) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab_to_available_range_.find(tab_id.id()) !=
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_to_available_range_.end()) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::pair<int, int>& range = tab_to_available_range_[tab_id.id()];
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range.first = std::min(navigation.index(), range.first);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range.second = std::max(navigation.index(), range.second);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation,
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   tab_id.id(), navigation));
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SessionService::TabRestored(WebContents* tab, bool pinned) {
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(tab);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(session_tab_helper->window_id()))
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BuildCommandsForTab(session_tab_helper->window_id(), tab, -1,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      pinned, &pending_commands(), NULL);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartSaveTimer();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetSelectedNavigationIndex(const SessionID& window_id,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                const SessionID& tab_id,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                int index) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab_to_available_range_.find(tab_id.id()) !=
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_to_available_range_.end()) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index < tab_to_available_range_[tab_id.id()].first ||
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        index > tab_to_available_range_[tab_id.id()].second) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The new index is outside the range of what we've archived, schedule
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // a reset.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResetFromCurrentBrowsers();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetSelectedNavigationIndexCommand(tab_id, index));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetSelectedTabInWindow(const SessionID& window_id,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int index) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetSelectedTabInWindow(window_id, index));
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetTabUserAgentOverride(
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_agent_override) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabUserAgentOverrideCommand(
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kCommandSetTabUserAgentOverride, tab_id.id(), user_agent_override));
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CancelableTaskTracker::TaskId SessionService::GetLastSession(
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SessionCallback& callback,
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CancelableTaskTracker* tracker) {
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // OnGotSessionCommands maps the SessionCommands to browser state, then run
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the callback.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ScheduleGetLastSessionCommands(
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SessionService::OnGotSessionCommands,
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this), callback),
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tracker);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::Save() {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool had_commands = !pending_commands().empty();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseSessionService::Save();
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (had_commands) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RecordSessionUpdateHistogramData(chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &last_updated_save_time_);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NotificationService::current()->Notify(
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Profile>(profile()),
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NotificationService::NoDetails());
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::Init() {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register for the notifications we're interested in.
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_NAV_LIST_PRUNED,
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_CHANGED,
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for NOTIFICATION_BROWSER_WINDOW_READY so that is_app() is set.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY,
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllBrowserContextsAndSources());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources());
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserList::AddObserver(this);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SessionService::processed_any_commands() {
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return backend()->inited() || !pending_commands().empty();
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::ShouldNewWindowStartSession() {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChromeOS and OSX have different ideas of application lifetime than
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the other platforms.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On ChromeOS opening a new window should never start a new session.
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!force_browser_not_alive_with_no_windows_)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_open_trackable_browsers_ &&
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !StartupBrowserCreator::InSynchronousProfileLaunch() &&
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !SessionRestore::IsRestoring(profile())
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // On OSX, a new window should not start a new session if it was opened
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // from the dock or the menubar.
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && !app_controller_mac::IsOpeningNewWindow()
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_MACOSX
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ) {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        Browser* browser) {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldNewWindowStartSession()) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're going from no tabbed browsers to a tabbed browser (and not in
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // process startup), restore the last session.
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (move_on_new_browser_) {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make the current session the last.
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MoveCurrentSessionToLastSession();
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      move_on_new_browser_ = false;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionStartupPref pref = StartupBrowserCreator::GetSessionStartupPref(
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *CommandLine::ForCurrentProcess(), profile());
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pref.type == SessionStartupPref::LAST) {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionRestore::RestoreSession(
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          profile(), browser,
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          browser ? browser->host_desktop_type() : chrome::GetActiveDesktop(),
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          browser ? 0 : SessionRestore::ALWAYS_CREATE_TABBED_BROWSER,
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          urls_to_open);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::Observe(int type,
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationSource& source,
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationDetails& details) {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All of our messages have the NavigationController as the source.
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_BROWSER_WINDOW_READY: {
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Browser* browser = content::Source<Browser>(source).ptr();
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!ShouldTrackBrowser(browser))
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RestoreIfNecessary(std::vector<GURL>(), browser);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetWindowType(browser->session_id(), browser->type(), app_type);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetWindowAppName(browser->session_id(), browser->app_name());
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_NAV_LIST_PRUNED: {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebContents* web_contents =
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::NavigationController>(source).ptr()->
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetWebContents();
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper* session_tab_helper =
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SessionTabHelper::FromWebContents(web_contents);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!session_tab_helper || web_contents->GetBrowserContext() != profile())
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<content::PrunedDetails> pruned_details(details);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pruned_details->from_front) {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabNavigationPathPrunedFromFront(
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->window_id(),
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->session_id(),
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pruned_details->count);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabNavigationPathPrunedFromBack(
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->window_id(),
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->session_id(),
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            web_contents->GetController().GetEntryCount());
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RecordSessionUpdateHistogramData(type,
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       &last_updated_nav_list_pruned_time_);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_NAV_ENTRY_CHANGED: {
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebContents* web_contents =
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::NavigationController>(source).ptr()->
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetWebContents();
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper* session_tab_helper =
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SessionTabHelper::FromWebContents(web_contents);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!session_tab_helper || web_contents->GetBrowserContext() != profile())
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<content::EntryChangedDetails> changed(details);
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const SerializedNavigationEntry navigation =
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SerializedNavigationEntry::FromNavigationEntry(
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              changed->index, *changed->changed_entry);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateTabNavigation(session_tab_helper->window_id(),
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          session_tab_helper->session_id(),
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          navigation);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_NAV_ENTRY_COMMITTED: {
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebContents* web_contents =
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::NavigationController>(source).ptr()->
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetWebContents();
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper* session_tab_helper =
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SessionTabHelper::FromWebContents(web_contents);
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!session_tab_helper || web_contents->GetBrowserContext() != profile())
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int current_entry_index =
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          web_contents->GetController().GetCurrentEntryIndex();
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetSelectedNavigationIndex(
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_tab_helper->window_id(),
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_tab_helper->session_id(),
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          current_entry_index);
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const SerializedNavigationEntry navigation =
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SerializedNavigationEntry::FromNavigationEntry(
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              current_entry_index,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              *web_contents->GetController().GetEntryAtIndex(
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  current_entry_index));
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateTabNavigation(
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_tab_helper->window_id(),
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_tab_helper->session_id(),
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          navigation);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<content::LoadCommittedDetails> changed(details);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (changed->type == content::NAVIGATION_TYPE_NEW_PAGE ||
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        changed->type == content::NAVIGATION_TYPE_EXISTING_PAGE) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordSessionUpdateHistogramData(type,
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &last_updated_nav_entry_commit_time_);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED: {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions::TabHelper* extension_tab_helper =
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<extensions::TabHelper>(source).ptr();
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (extension_tab_helper->web_contents()->GetBrowserContext() !=
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              profile()) {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (extension_tab_helper->extension_app()) {
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionTabHelper* session_tab_helper =
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            SessionTabHelper::FromWebContents(
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                extension_tab_helper->web_contents());
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetTabExtensionAppID(session_tab_helper->window_id(),
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             session_tab_helper->session_id(),
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             extension_tab_helper->extension_app()->id());
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::OnBrowserSetLastActive(Browser* browser) {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldTrackBrowser(browser))
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateSetActiveWindowCommand(browser->session_id()));
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SetTabExtensionAppID(
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_app_id) {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldTrackChangesToWindow(window_id))
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSetTabExtensionAppIDCommand(kCommandSetExtensionAppID,
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_id.id(), extension_app_id));
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetSelectedTabInWindow(
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index) {
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectedTabInIndexPayload payload = { 0 };
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = window_id.id();
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = index;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command = new SessionCommand(kCommandSetSelectedTabInIndex,
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 sizeof(payload));
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetTabWindowCommand(
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type payload[] = { window_id.id(), tab_id.id() };
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandSetTabWindow, sizeof(payload));
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), payload, sizeof(payload));
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetWindowBoundsCommand(
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& bounds,
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::WindowShowState show_state) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowBoundsPayload3 payload = { 0 };
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.window_id = window_id.id();
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.x = bounds.x();
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.y = bounds.y();
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.w = bounds.width();
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.h = bounds.height();
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.show_state = AdjustShowState(show_state);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command = new SessionCommand(kCommandSetWindowBounds3,
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               sizeof(payload));
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetTabIndexInWindowCommand(
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int new_index) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabIndexInWindowPayload payload = { 0 };
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id.id();
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = new_index;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandSetTabIndexInWindow, sizeof(payload));
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateTabClosedCommand(
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID::id_type tab_id) {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClosedPayload payload;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Because of what appears to be a compiler bug setting payload to {0} doesn't
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set the padding to 0, resulting in Purify reporting an UMR when we write
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the structure to disk. To avoid this we explicitly memset the struct.
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&payload, 0, sizeof(payload));
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.close_time = Time::Now().ToInternalValue();
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandTabClosed, sizeof(payload));
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateWindowClosedCommand(
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID::id_type window_id) {
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClosedPayload payload;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See comment in CreateTabClosedCommand as to why we do this.
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&payload, 0, sizeof(payload));
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = window_id;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.close_time = Time::Now().ToInternalValue();
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandWindowClosed, sizeof(payload));
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetSelectedNavigationIndexCommand(
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index) {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectedNavigationIndexPayload payload = { 0 };
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = tab_id.id();
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = index;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command = new SessionCommand(
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kCommandSetSelectedNavigationIndex, sizeof(payload));
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetWindowTypeCommand(
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id,
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WindowType type) {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowTypePayload payload = { 0 };
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.id = window_id.id();
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.index = static_cast<int32>(type);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command = new SessionCommand(
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kCommandSetWindowType, sizeof(payload));
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreatePinnedStateCommand(
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_pinned) {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PinnedStatePayload payload = { 0 };
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.tab_id = tab_id.id();
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload.pinned_state = is_pinned;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandSetPinnedState, sizeof(payload));
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSessionStorageAssociatedCommand(
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& tab_id,
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& session_storage_persistent_id) {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pickle pickle;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pickle.WriteInt(tab_id.id());
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pickle.WriteString(session_storage_persistent_id);
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new SessionCommand(kCommandSessionStorageAssociated, pickle);
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionCommand* SessionService::CreateSetActiveWindowCommand(
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id) {
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveWindowPayload payload = 0;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload = window_id.id();
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionCommand* command =
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SessionCommand(kCommandSetActiveWindow, sizeof(payload));
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(command->contents(), &payload, sizeof(payload));
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::OnGotSessionCommands(
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SessionCallback& callback,
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScopedVector<SessionCommand> commands) {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<SessionWindow> valid_windows;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type active_window_id = 0;
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestoreSessionFromCommands(
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      commands.get(), &valid_windows.get(), &active_window_id);
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(valid_windows.Pass(), active_window_id);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RestoreSessionFromCommands(
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<SessionCommand*>& commands,
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionWindow*>* valid_windows,
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type* active_window_id) {
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionTab*> tabs;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionWindow*> windows;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "RestoreSessionFromCommands " << commands.size();
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CreateTabsAndWindows(commands, &tabs, &windows, active_window_id)) {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddTabsToWindows(&tabs, &windows);
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows);
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateSelectedTabIndex(valid_windows);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteValues(&tabs);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't delete conents of windows, that is done by the caller as all
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // valid windows are added to valid_windows.
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::UpdateSelectedTabIndex(
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionWindow*>* windows) {
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<SessionWindow*>::const_iterator i = windows->begin();
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != windows->end(); ++i) {
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See note in SessionWindow as to why we do this.
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int new_index = 0;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<SessionTab*>::const_iterator j = (*i)->tabs.begin();
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         j != (*i)->tabs.end(); ++j) {
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*j)->tab_visual_index == (*i)->selected_tab_index) {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_index = static_cast<int>(j - (*i)->tabs.begin());
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*i)->selected_tab_index = new_index;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionWindow* SessionService::GetWindow(
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type window_id,
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdToSessionWindow* windows) {
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionWindow*>::iterator i = windows->find(window_id);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == windows->end()) {
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionWindow* window = new SessionWindow();
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->window_id.set_id(window_id);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*windows)[window_id] = window;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return window;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return i->second;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionTab* SessionService::GetTab(
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type tab_id,
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdToSessionTab* tabs) {
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(tabs);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionTab*>::iterator i = tabs->find(tab_id);
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == tabs->end()) {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionTab* tab = new SessionTab();
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab->tab_id.set_id(tab_id);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*tabs)[tab_id] = tab;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return tab;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return i->second;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::vector<SerializedNavigationEntry>::iterator
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionService::FindClosestNavigationWithIndex(
914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<SerializedNavigationEntry>* navigations,
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index) {
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(navigations);
917c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (std::vector<SerializedNavigationEntry>::iterator
918c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           i = navigations->begin(); i != navigations->end(); ++i) {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->index() >= index)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return navigations->end();
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Function used in sorting windows. Sorting is done based on window id. As
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// window ids increment for each new window, this effectively sorts by creation
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time.
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool WindowOrderSortFunction(const SessionWindow* w1,
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const SessionWindow* w2) {
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return w1->window_id.id() < w2->window_id.id();
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Compares the two tabs based on visual index.
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool TabVisualIndexSortFunction(const SessionTab* t1,
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const SessionTab* t2) {
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int delta = t1->tab_visual_index - t2->tab_visual_index;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return delta == 0 ? (t1->tab_id.id() < t2->tab_id.id()) : (delta < 0);
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::SortTabsBasedOnVisualOrderAndPrune(
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<int, SessionWindow*>* windows,
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionWindow*>* valid_windows) {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionWindow*>::iterator i = windows->begin();
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (i != windows->end()) {
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionWindow* window = i->second;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppType app_type = window->app_name.empty() ? TYPE_NORMAL : TYPE_APP;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window->tabs.empty() || window->is_constrained ||
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !should_track_changes_for_browser_type(
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<Browser::Type>(window->type),
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            app_type)) {
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete window;
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windows->erase(i++);
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Valid window; sort the tabs and add it to the list of valid windows.
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::sort(window->tabs.begin(), window->tabs.end(),
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &TabVisualIndexSortFunction);
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Otherwise, add the window such that older windows appear first.
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (valid_windows->empty()) {
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        valid_windows->push_back(window);
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        valid_windows->insert(
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            std::upper_bound(valid_windows->begin(), valid_windows->end(),
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             window, &WindowOrderSortFunction),
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            window);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::AddTabsToWindows(std::map<int, SessionTab*>* tabs,
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::map<int, SessionWindow*>* windows) {
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "AddTabsToWindws";
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Tabs " << tabs->size() << ", windows " << windows->size();
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SessionTab*>::iterator i = tabs->begin();
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (i != tabs->end()) {
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionTab* tab = i->second;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tab->window_id.id() && !tab->navigations.empty()) {
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionWindow* window = GetWindow(tab->window_id.id(), windows);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window->tabs.push_back(tab);
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tabs->erase(i++);
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See note in SessionTab as to why we do this.
984c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::vector<SerializedNavigationEntry>::iterator j =
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FindClosestNavigationWithIndex(&(tab->navigations),
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         tab->current_navigation_index);
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (j == tab->navigations.end()) {
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tab->current_navigation_index =
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<int>(tab->navigations.size() - 1);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tab->current_navigation_index =
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<int>(j - tab->navigations.begin());
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Never got a set tab index in window, or tabs are empty, nothing
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to do.
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::CreateTabsAndWindows(
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<SessionCommand*>& data,
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<int, SessionTab*>* tabs,
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<int, SessionWindow*>* windows,
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type* active_window_id) {
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the file is corrupt (command with wrong size, or unknown command), we
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // still return true and attempt to restore what we we can.
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CreateTabsAndWindows";
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  startup_metric_utils::ScopedSlowStartupUMA
10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_timer("Startup.SlowStartupSessionServiceCreateTabsAndWindows");
10132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<SessionCommand*>::const_iterator i = data.begin();
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != data.end(); ++i) {
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionCommand* command = *i;
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Read command " << (int) command->id();
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (command->id()) {
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetTabWindow: {
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type payload[2];
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(payload, sizeof(payload))) {
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(payload[1], tabs)->window_id.set_id(payload[0]);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is here for forward migration only.  New data is saved with
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |kCommandSetWindowBounds3|.
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetWindowBounds2: {
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WindowBoundsPayload2 payload;
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x,
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.y,
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.w,
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.h);
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.window_id, windows)->show_state =
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            payload.is_maximized ?
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ui::SHOW_STATE_MAXIMIZED : ui::SHOW_STATE_NORMAL;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetWindowBounds3: {
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WindowBoundsPayload3 payload;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x,
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.y,
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.w,
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              payload.h);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // SHOW_STATE_INACTIVE is not persisted.
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::WindowShowState show_state = ui::SHOW_STATE_NORMAL;
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (payload.show_state > ui::SHOW_STATE_DEFAULT &&
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            payload.show_state < ui::SHOW_STATE_END &&
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            payload.show_state != ui::SHOW_STATE_INACTIVE) {
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          show_state = static_cast<ui::WindowShowState>(payload.show_state);
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED();
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.window_id, windows)->show_state = show_state;
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetTabIndexInWindow: {
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabIndexInWindowPayload payload;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(payload.id, tabs)->tab_visual_index = payload.index;
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandTabClosedObsolete:
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandWindowClosedObsolete:
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandTabClosed:
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandWindowClosed: {
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ClosedPayload payload;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload)) &&
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !MigrateClosedPayload(*command, &payload)) {
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (command->id() == kCommandTabClosed ||
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            command->id() == kCommandTabClosedObsolete) {
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delete GetTab(payload.id, tabs);
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tabs->erase(payload.id);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delete GetWindow(payload.id, windows);
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          windows->erase(payload.id);
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandTabNavigationPathPrunedFromBack: {
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabNavigationPathPrunedFromBackPayload payload;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionTab* tab = GetTab(payload.id, tabs);
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tab->navigations.erase(
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FindClosestNavigationWithIndex(&(tab->navigations), payload.index),
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tab->navigations.end());
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandTabNavigationPathPrunedFromFront: {
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TabNavigationPathPrunedFromFrontPayload payload;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload)) ||
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            payload.index <= 0) {
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionTab* tab = GetTab(payload.id, tabs);
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Update the selected navigation index.
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tab->current_navigation_index =
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            std::max(-1, tab->current_navigation_index - payload.index);
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // And update the index of existing navigations.
1130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        for (std::vector<SerializedNavigationEntry>::iterator
1131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 i = tab->navigations.begin();
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             i != tab->navigations.end();) {
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          i->set_index(i->index() - payload.index);
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (i->index() < 0)
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            i = tab->navigations.erase(i);
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          else
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ++i;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandUpdateTabNavigation: {
1143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        SerializedNavigationEntry navigation;
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type tab_id;
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!RestoreUpdateTabNavigationCommand(
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *command, &navigation, &tab_id)) {
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionTab* tab = GetTab(tab_id, tabs);
1151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        std::vector<SerializedNavigationEntry>::iterator i =
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FindClosestNavigationWithIndex(&(tab->navigations),
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           navigation.index());
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (i != tab->navigations.end() && i->index() == navigation.index())
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *i = navigation;
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tab->navigations.insert(i, navigation);
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetSelectedNavigationIndex: {
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SelectedNavigationIndexPayload payload;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(payload.id, tabs)->current_navigation_index = payload.index;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetSelectedTabInIndex: {
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SelectedTabInIndexPayload payload;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.id, windows)->selected_tab_index = payload.index;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetWindowType: {
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WindowTypePayload payload;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.id, windows)->is_constrained = false;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(payload.id, windows)->type =
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            BrowserTypeForWindowType(
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                static_cast<WindowType>(payload.index));
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetPinnedState: {
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PinnedStatePayload payload;
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(payload.tab_id, tabs)->pinned = payload.pinned_state;
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetWindowAppName: {
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type window_id;
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string app_name;
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!RestoreSetWindowAppNameCommand(*command, &window_id, &app_name))
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetWindow(window_id, windows)->app_name.swap(app_name);
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetExtensionAppID: {
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type tab_id;
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string extension_app_id;
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!RestoreSetTabExtensionAppIDCommand(
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *command, &tab_id, &extension_app_id)) {
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(tab_id, tabs)->extension_app_id.swap(extension_app_id);
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetTabUserAgentOverride: {
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type tab_id;
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string user_agent_override;
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!RestoreSetTabUserAgentOverrideCommand(
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *command, &tab_id, &user_agent_override)) {
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(tab_id, tabs)->user_agent_override.swap(user_agent_override);
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSessionStorageAssociated: {
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle());
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionID::id_type command_tab_id;
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string session_storage_persistent_id;
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PickleIterator iter(*command_pickle.get());
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command_pickle->ReadInt(&iter, &command_tab_id) ||
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !command_pickle->ReadString(&iter, &session_storage_persistent_id))
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Associate the session storage back.
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTab(command_tab_id, tabs)->session_storage_persistent_id =
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_storage_persistent_id;
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kCommandSetActiveWindow: {
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ActiveWindowPayload payload;
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!command->GetPayload(&payload, sizeof(payload))) {
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          VLOG(1) << "Failed reading command " << command->id();
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *active_window_id = payload;
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VLOG(1) << "Failed reading an unknown command " << command->id();
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SessionService::BuildCommandsForTab(const SessionID& window_id,
12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         WebContents* tab,
12732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int index_in_window,
12742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         bool is_pinned,
12752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         std::vector<SessionCommand*>* commands,
12762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         IdToRange* tab_to_available_range) {
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(tab && commands && window_id.id());
12782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SessionTabHelper* session_tab_helper = SessionTabHelper::FromWebContents(tab);
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SessionID& session_id(session_tab_helper->session_id());
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(CreateSetTabWindowCommand(window_id, session_id));
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int current_index = tab->GetController().GetCurrentEntryIndex();
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int min_index = std::max(0,
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 current_index - max_persist_navigation_count);
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int max_index =
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::min(current_index + max_persist_navigation_count,
12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               tab->GetController().GetEntryCount());
12882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int pending_index = tab->GetController().GetPendingEntryIndex();
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab_to_available_range) {
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*tab_to_available_range)[session_id.id()] =
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::pair<int, int>(min_index, max_index);
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_pinned) {
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(CreatePinnedStateCommand(session_id, true));
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::TabHelper* extensions_tab_helper =
12992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::TabHelper::FromWebContents(tab);
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extensions_tab_helper->extension_app()) {
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateSetTabExtensionAppIDCommand(
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            kCommandSetExtensionAppID, session_id.id(),
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            extensions_tab_helper->extension_app()->id()));
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& ua_override = tab->GetUserAgentOverride();
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ua_override.empty()) {
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateSetTabUserAgentOverrideCommand(
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            kCommandSetTabUserAgentOverride, session_id.id(), ua_override));
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = min_index; i < max_index; ++i) {
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const NavigationEntry* entry = (i == pending_index) ?
13162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tab->GetController().GetPendingEntry() :
13172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tab->GetController().GetEntryAtIndex(i);
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(entry);
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ShouldTrackEntry(entry->GetVirtualURL())) {
1320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const SerializedNavigationEntry navigation =
1321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SerializedNavigationEntry::FromNavigationEntry(i, *entry);
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      commands->push_back(
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateUpdateTabNavigationCommand(
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kCommandUpdateTabNavigation, session_id.id(), navigation));
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateSetSelectedNavigationIndexCommand(session_id, current_index));
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index_in_window != -1) {
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateSetTabIndexInWindowCommand(session_id, index_in_window));
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record the association between the sessionStorage namespace and the tab.
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::SessionStorageNamespace* session_storage_namespace =
13372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tab->GetController().GetDefaultSessionStorageNamespace();
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSessionStorageAssociatedCommand(
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_tab_helper->session_id(),
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_storage_namespace->persistent_id()));
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::BuildCommandsForBrowser(
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser,
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionCommand*>* commands,
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdToRange* tab_to_available_range,
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<SessionID::id_type>* windows_to_track) {
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(browser && commands);
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(browser->session_id().id());
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::WindowShowState show_state = ui::SHOW_STATE_NORMAL;
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (browser->window()->IsMaximized())
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    show_state = ui::SHOW_STATE_MAXIMIZED;
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (browser->window()->IsMinimized())
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    show_state = ui::SHOW_STATE_MINIMIZED;
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateSetWindowBoundsCommand(browser->session_id(),
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   browser->window()->GetRestoredBounds(),
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   show_state));
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(CreateSetWindowTypeCommand(
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser->session_id(), WindowTypeForBrowserType(browser->type())));
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!browser->app_name().empty()) {
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commands->push_back(CreateSetWindowAppNameCommand(
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kCommandSetWindowAppName,
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->session_id().id(),
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->app_name()));
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  windows_to_track->insert(browser->session_id().id());
13732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TabStripModel* tab_strip = browser->tab_strip_model();
13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < tab_strip->count(); ++i) {
13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebContents* tab = tab_strip->GetWebContentsAt(i);
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(tab);
13772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BuildCommandsForTab(browser->session_id(), tab, i,
13782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        tab_strip->IsTabPinned(i),
13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        commands, tab_to_available_range);
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  commands->push_back(
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateSetSelectedTabInWindow(browser->session_id(),
13842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   browser->tab_strip_model()->active_index()));
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::BuildCommandsFromBrowsers(
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<SessionCommand*>* commands,
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdToRange* tab_to_available_range,
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<SessionID::id_type>* windows_to_track) {
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(commands);
13922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
13932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = *it;
13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Make sure the browser has tabs and a window. Browser's destructor
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // removes itself from the BrowserList. When a browser is closed the
13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // destructor is not necessarily run immediately. This means it's possible
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for us to get a handle to a browser that is about to be removed. If
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the tab count is 0 or the window is NULL, the browser is about to be
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // deleted, so we ignore it.
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ShouldTrackBrowser(browser) && browser->tab_strip_model()->count() &&
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->window()) {
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BuildCommandsForBrowser(browser, commands, tab_to_available_range,
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              windows_to_track);
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::ScheduleReset() {
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_pending_reset(true);
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&pending_commands());
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tab_to_available_range_.clear();
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windows_tracking_.clear();
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BuildCommandsFromBrowsers(&pending_commands(), &tab_to_available_range_,
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &windows_tracking_);
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!windows_tracking_.empty()) {
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're lazily created on startup and won't get an initial batch of
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SetWindowType messages. Set these here to make sure our state is correct.
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_open_trackable_browsers_ = true;
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    move_on_new_browser_ = true;
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartSaveTimer();
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::ReplacePendingCommand(SessionCommand* command) {
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We optimize page navigations, which can happen quite frequently and
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are expensive. And activation is like Highlander, there can only be one!
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command->id() != kCommandUpdateTabNavigation &&
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command->id() != kCommandSetActiveWindow) {
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<SessionCommand*>::reverse_iterator i =
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       pending_commands().rbegin(); i != pending_commands().rend(); ++i) {
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionCommand* existing_command = *i;
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (command->id() == kCommandUpdateTabNavigation &&
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        existing_command->id() == kCommandUpdateTabNavigation) {
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle());
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PickleIterator iterator(*command_pickle);
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionID::id_type command_tab_id;
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int command_nav_index;
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!command_pickle->ReadInt(&iterator, &command_tab_id) ||
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !command_pickle->ReadInt(&iterator, &command_nav_index)) {
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionID::id_type existing_tab_id;
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int existing_nav_index;
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Creating a pickle like this means the Pickle references the data from
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the command. Make sure we delete the pickle before the command, else
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the pickle references deleted memory.
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_ptr<Pickle> existing_pickle(existing_command->PayloadAsPickle());
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iterator = PickleIterator(*existing_pickle);
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!existing_pickle->ReadInt(&iterator, &existing_tab_id) ||
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !existing_pickle->ReadInt(&iterator, &existing_nav_index)) {
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (existing_tab_id == command_tab_id &&
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          existing_nav_index == command_nav_index) {
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // existing_command is an update for the same tab/index pair. Replace
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // it with the new one. We need to add to the end of the list just in
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // case there is a prune command after the update command.
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete existing_command;
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_commands().erase(i.base() - 1);
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_commands().push_back(command);
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (command->id() == kCommandSetActiveWindow &&
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        existing_command->id() == kCommandSetActiveWindow) {
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *i = command;
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete existing_command;
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::ScheduleCommand(SessionCommand* command) {
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(command);
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ReplacePendingCommand(command))
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseSessionService::ScheduleCommand(command);
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't schedule a reset on tab closed/window closed. Otherwise we may
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lose tabs/windows we want to restore from if we exit right after this.
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pending_reset() && pending_window_close_ids_.empty() &&
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      commands_since_reset() >= kWritesPerReset &&
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (command->id() != kCommandTabClosed &&
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       command->id() != kCommandWindowClosed)) {
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleReset();
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::CommitPendingCloses() {
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingTabCloseIDs::iterator i = pending_tab_close_ids_.begin();
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_tab_close_ids_.end(); ++i) {
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateTabClosedCommand(*i));
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tab_close_ids_.clear();
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingWindowCloseIDs::iterator i = pending_window_close_ids_.begin();
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_window_close_ids_.end(); ++i) {
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleCommand(CreateWindowClosedCommand(*i));
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_window_close_ids_.clear();
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::IsOnlyOneTabLeft() const {
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile()) {
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're testing, always return false.
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int window_count = 0;
15152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
15162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = *it;
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID::id_type window_id = browser->session_id().id();
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ShouldTrackBrowser(browser) &&
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window_closing_ids_.find(window_id) == window_closing_ids_.end()) {
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (++window_count > 1)
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // By the time this is invoked the tab has been removed. As such, we use
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // > 0 here rather than > 1.
15242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (browser->tab_strip_model()->count() > 0)
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::HasOpenTrackableBrowsers(
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id) const {
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile()) {
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're testing, always return false.
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
15392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = *it;
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID::id_type browser_id = browser->session_id().id();
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (browser_id != window_id.id() &&
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window_closing_ids_.find(browser_id) == window_closing_ids_.end() &&
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ShouldTrackBrowser(browser)) {
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::ShouldTrackChangesToWindow(
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionID& window_id) const {
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return windows_tracking_.find(window_id.id()) != windows_tracking_.end();
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::ShouldTrackBrowser(Browser* browser) const {
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL;
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return browser->profile() == profile() &&
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         should_track_changes_for_browser_type(browser->type(), app_type);
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionService::should_track_changes_for_browser_type(Browser::Type type,
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           AppType app_type) {
15632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
15642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Restore app popups for chromeos alone.
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == Browser::TYPE_POPUP && app_type == TYPE_APP)
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return type == Browser::TYPE_TABBED ||
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (type == Browser::TYPE_POPUP && browser_defaults::kRestorePopups);
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SessionService::WindowType SessionService::WindowTypeForBrowserType(
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser::Type type) {
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Browser::TYPE_POPUP:
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TYPE_POPUP;
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Browser::TYPE_TABBED:
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TYPE_TABBED;
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(false);
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TYPE_TABBED;
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Browser::Type SessionService::BrowserTypeForWindowType(WindowType type) {
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_POPUP:
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Browser::TYPE_POPUP;
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_TABBED:
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Browser::TYPE_TABBED;
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordSessionUpdateHistogramData(int type,
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeTicks* last_updated_time) {
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!last_updated_time->is_null()) {
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta delta = base::TimeTicks::Now() - *last_updated_time;
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're interested in frequent updates periods longer than
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 10 minutes.
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool use_long_period = false;
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delta >= save_delay_in_mins_) {
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_long_period = true;
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (type) {
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case chrome::NOTIFICATION_SESSION_SERVICE_SAVED :
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSaveTime(delta, use_long_period);
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSessionNavigationOrTab(delta, use_long_period);
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case content::NOTIFICATION_WEB_CONTENTS_DESTROYED:
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedTabClosed(delta, use_long_period);
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSessionNavigationOrTab(delta, use_long_period);
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case content::NOTIFICATION_NAV_LIST_PRUNED:
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedNavListPruned(delta, use_long_period);
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSessionNavigationOrTab(delta, use_long_period);
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case content::NOTIFICATION_NAV_ENTRY_COMMITTED:
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedNavEntryCommit(delta, use_long_period);
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordUpdatedSessionNavigationOrTab(delta, use_long_period);
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "Bad type sent to RecordSessionUpdateHistogramData";
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*last_updated_time) = base::TimeTicks::Now();
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedTabClosed(base::TimeDelta delta,
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            bool use_long_period) {
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.TabClosedPeriod");
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.TabClosedLongPeriod");
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedNavListPruned(base::TimeDelta delta,
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                bool use_long_period) {
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.NavigationListPrunedPeriod");
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.NavigationListPrunedLongPeriod");
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedNavEntryCommit(base::TimeDelta delta,
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 bool use_long_period) {
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.NavEntryCommittedPeriod");
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.NavEntryCommittedLongPeriod");
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedSessionNavigationOrTab(base::TimeDelta delta,
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                         bool use_long_period) {
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.NavOrTabUpdatePeriod");
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.NavOrTabUpdateLongPeriod");
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::RecordUpdatedSaveTime(base::TimeDelta delta,
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool use_long_period) {
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("SessionRestore.SavePeriod");
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_TIMES(name,
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta,
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 2500ms is the default save delay.
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_millis_,
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_delay_in_mins_,
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      50);
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_long_period) {
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string long_name_("SessionRestore.SaveLongPeriod");
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta,
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_mins_,
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_delay_in_hrs_,
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        50);
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabInserted(WebContents* contents) {
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionTabHelper* session_tab_helper =
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper::FromWebContents(contents);
17292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ShouldTrackChangesToWindow(session_tab_helper->window_id()))
17302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetTabWindow(session_tab_helper->window_id(),
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               session_tab_helper->session_id());
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::TabHelper* extensions_tab_helper =
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions::TabHelper::FromWebContents(contents);
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extensions_tab_helper &&
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions_tab_helper->extension_app()) {
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetTabExtensionAppID(
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_tab_helper->window_id(),
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_tab_helper->session_id(),
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions_tab_helper->extension_app()->id());
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record the association between the SessionStorageNamespace and the
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tab.
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(ajwong): This should be processing the whole map rather than
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // just the default. This in particular will not work for tabs with only
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // isolated apps which won't have a default partition.
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::SessionStorageNamespace* session_storage_namespace =
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      contents->GetController().GetDefaultSessionStorageNamespace();
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleCommand(CreateSessionStorageAssociatedCommand(
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_tab_helper->session_id(),
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_storage_namespace->persistent_id()));
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_storage_namespace->SetShouldPersist(true);
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SessionService::TabClosing(WebContents* contents) {
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow the associated sessionStorage to get deleted; it won't be needed
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the session restore.
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::SessionStorageNamespace* session_storage_namespace =
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      contents->GetController().GetDefaultSessionStorageNamespace();
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_storage_namespace->SetShouldPersist(false);
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionTabHelper* session_tab_helper =
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionTabHelper::FromWebContents(contents);
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabClosed(session_tab_helper->window_id(),
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_tab_helper->session_id(),
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            contents->GetClosedByUserGesture());
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecordSessionUpdateHistogramData(content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &last_updated_tab_closed_time_);
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1771