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