1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sessions/session_service.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <algorithm> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <limits> 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <set> 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <vector> 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_vector.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/pickle.h" 173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_tab_helper.h" 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/session_startup_pref.h" 2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sessions/session_backend.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sessions/session_command.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sessions/session_restore.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sessions/session_types.h" 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/tabs/tab_strip_model.h" 264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser_init.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h" 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h" 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension.h" 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/navigation_controller.h" 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/navigation_entry.h" 33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h" 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX) 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/app_controller_cppsafe_mac.h" 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Identifier for commands written to file. 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandSetTabWindow = 0; 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// kCommandSetWindowBounds is no longer used (it's superseded by 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// kCommandSetWindowBounds2). I leave it here to document what it was. 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static const SessionCommand::id_type kCommandSetWindowBounds = 1; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandSetTabIndexInWindow = 2; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandTabClosed = 3; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandWindowClosed = 4; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCommandTabNavigationPathPrunedFromBack = 5; 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandUpdateTabNavigation = 6; 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandSetSelectedNavigationIndex = 7; 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandSetSelectedTabInIndex = 8; 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandSetWindowType = 9; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandSetWindowBounds2 = 10; 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCommandTabNavigationPathPrunedFromFront = 11; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandSetPinnedState = 12; 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SessionCommand::id_type kCommandSetExtensionAppID = 13; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Every kWritesPerReset commands triggers recreating the file. 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kWritesPerReset = 250; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The callback from GetLastSession is internally routed to SessionService 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// first and then the caller. This is done so that the SessionWindows can be 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// recreated from the SessionCommands and the SessionWindows passed to the 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// caller. The following class is used for this. 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass InternalSessionRequest 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : public BaseSessionService::InternalGetCommandsRequest { 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InternalSessionRequest( 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CallbackType* callback, 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionService::SessionCallback* real_callback) 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : BaseSessionService::InternalGetCommandsRequest(callback), 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch real_callback(real_callback) { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The callback supplied to GetLastSession and GetCurrentSession. 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SessionService::SessionCallback> real_callback; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~InternalSessionRequest() {} 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(InternalSessionRequest); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Various payload structures. 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct ClosedPayload { 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type id; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 close_time; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct WindowBoundsPayload2 { 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type window_id; 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 x; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 y; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 w; 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 h; 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_maximized; 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct IDAndIndexPayload { 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type id; 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 index; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef IDAndIndexPayload TabIndexInWindowPayload; 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef IDAndIndexPayload TabNavigationPathPrunedFromBackPayload; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef IDAndIndexPayload SelectedNavigationIndexPayload; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef IDAndIndexPayload SelectedTabInIndexPayload; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef IDAndIndexPayload WindowTypePayload; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef IDAndIndexPayload TabNavigationPathPrunedFromFrontPayload; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct PinnedStatePayload { 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type tab_id; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool pinned_state; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SessionService ------------------------------------------------------------- 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionService::SessionService(Profile* profile) 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : BaseSessionService(SESSION_RESTORE, profile, FilePath()), 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_open_trackable_browsers_(false), 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch move_on_new_browser_(false), 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)), 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_(base::TimeDelta::FromMinutes(10)), 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_hrs_(base::TimeDelta::FromHours(8)) { 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Init(); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionService::SessionService(const FilePath& save_path) 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : BaseSessionService(SESSION_RESTORE, NULL, save_path), 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_open_trackable_browsers_(false), 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch move_on_new_browser_(false), 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)), 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_(base::TimeDelta::FromMinutes(10)), 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_hrs_(base::TimeDelta::FromHours(8)) { 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Init(); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionService::~SessionService() { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Save(); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open) { 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return RestoreIfNecessary(urls_to_open, NULL); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::ResetFromCurrentBrowsers() { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleReset(); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::MoveCurrentSessionToLastSession() { 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_tab_close_ids_.clear(); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_closing_ids_.clear(); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_window_close_ids_.clear(); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Save(); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!backend_thread()) { 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch backend()->MoveCurrentSessionToLastSession(); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch backend_thread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch backend(), &SessionBackend::MoveCurrentSessionToLastSession)); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::SetTabWindow(const SessionID& window_id, 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id) { 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateSetTabWindowCommand(window_id, tab_id)); 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::SetWindowBounds(const SessionID& window_id, 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Rect& bounds, 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_maximized) { 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateSetWindowBoundsCommand(window_id, bounds, 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_maximized)); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::SetTabIndexInWindow(const SessionID& window_id, 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_index) { 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateSetTabIndexInWindowCommand(tab_id, new_index)); 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::SetPinnedState(const SessionID& window_id, 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_pinned) { 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreatePinnedStateCommand(tab_id, is_pinned)); 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::TabClosed(const SessionID& window_id, 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool closed_by_user_gesture) { 218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!tab_id.id()) 219731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; // Hapens when the tab is replaced. 220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IdToRange::iterator i = tab_to_available_range_.find(tab_id.id()); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i != tab_to_available_range_.end()) 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_to_available_range_.erase(i); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (find(pending_window_close_ids_.begin(), pending_window_close_ids_.end(), 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_id.id()) != pending_window_close_ids_.end()) { 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tab is in last window. Don't commit it immediately, instead add it to the 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // list of tabs to close. If the user creates another window, the close is 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // committed. 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_tab_close_ids_.insert(tab_id.id()); 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (find(window_closing_ids_.begin(), window_closing_ids_.end(), 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_id.id()) != window_closing_ids_.end() || 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !IsOnlyOneTabLeft() || 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch closed_by_user_gesture) { 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Close is the result of one of the following: 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // . window close (and it isn't the last window). 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // . closing a tab and there are other windows/tabs open. 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // . closed by a user gesture. 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // In all cases we need to mark the tab as explicitly closed. 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateTabClosedCommand(tab_id.id())); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // User closed the last tab in the last tabbed browser. Don't mark the 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // tab closed. 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_tab_close_ids_.insert(tab_id.id()); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_open_trackable_browsers_ = false; 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::WindowClosing(const SessionID& window_id) { 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The window is about to close. If there are other tabbed browsers with the 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // same original profile commit the close immediately. 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: if the user chooses the exit menu item session service is destroyed 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and this code isn't hit. 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_open_trackable_browsers_) { 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Closing a window can never make has_open_trackable_browsers_ go from 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // false to true, so only update it if already true. 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_open_trackable_browsers_ = HasOpenTrackableBrowsers(window_id); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (should_record_close_as_pending()) 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_window_close_ids_.insert(window_id.id()); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_closing_ids_.insert(window_id.id()); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::WindowClosed(const SessionID& window_id) { 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch windows_tracking_.erase(window_id.id()); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (window_closing_ids_.find(window_id.id()) != window_closing_ids_.end()) { 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_closing_ids_.erase(window_id.id()); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateWindowClosedCommand(window_id.id())); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (pending_window_close_ids_.find(window_id.id()) == 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_window_close_ids_.end()) { 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We'll hit this if user closed the last tab in a window. 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_open_trackable_browsers_ = HasOpenTrackableBrowsers(window_id); 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (should_record_close_as_pending()) 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_window_close_ids_.insert(window_id.id()); 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateWindowClosedCommand(window_id.id())); 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::SetWindowType(const SessionID& window_id, 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser::Type type) { 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!should_track_changes_for_browser_type(type)) 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch windows_tracking_.insert(window_id.id()); 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The user created a new tabbed browser with our profile. Commit any 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // pending closes. 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CommitPendingCloses(); 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_open_trackable_browsers_ = true; 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch move_on_new_browser_ = true; 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand( 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateSetWindowTypeCommand(window_id, WindowTypeForBrowserType(type))); 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::TabNavigationPathPrunedFromBack(const SessionID& window_id, 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int count) { 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabNavigationPathPrunedFromBackPayload payload = { 0 }; 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.id = tab_id.id(); 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.index = count; 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new SessionCommand(kCommandTabNavigationPathPrunedFromBack, 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(payload)); 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(command); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::TabNavigationPathPrunedFromFront( 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& window_id, 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int count) { 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the range of indices. 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_to_available_range_.find(tab_id.id()) != 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_to_available_range_.end()) { 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::pair<int, int>& range = tab_to_available_range_[tab_id.id()]; 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch range.first = std::max(0, range.first - count); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch range.second = std::max(0, range.second - count); 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabNavigationPathPrunedFromFrontPayload payload = { 0 }; 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.id = tab_id.id(); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.index = count; 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new SessionCommand(kCommandTabNavigationPathPrunedFromFront, 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(payload)); 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(command); 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::UpdateTabNavigation(const SessionID& window_id, 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NavigationEntry& entry) { 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackEntry(entry) || !ShouldTrackChangesToWindow(window_id)) 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_to_available_range_.find(tab_id.id()) != 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_to_available_range_.end()) { 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::pair<int, int>& range = tab_to_available_range_[tab_id.id()]; 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch range.first = std::min(index, range.first); 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch range.second = std::max(index, range.second); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_id.id(), index, entry)); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::TabRestored(NavigationController* controller, 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool pinned) { 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(controller->window_id())) 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BuildCommandsForTab(controller->window_id(), controller, -1, 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pinned, &pending_commands(), NULL); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartSaveTimer(); 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::SetSelectedNavigationIndex(const SessionID& window_id, 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_to_available_range_.find(tab_id.id()) != 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_to_available_range_.end()) { 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index < tab_to_available_range_[tab_id.id()].first || 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index > tab_to_available_range_[tab_id.id()].second) { 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The new index is outside the range of what we've archived, schedule 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a reset. 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResetFromCurrentBrowsers(); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateSetSelectedNavigationIndexCommand(tab_id, index)); 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::SetSelectedTabInWindow(const SessionID& window_id, 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateSetSelectedTabInWindow(window_id, index)); 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionService::Handle SessionService::GetLastSession( 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CancelableRequestConsumerBase* consumer, 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCallback* callback) { 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ScheduleGetLastSessionCommands( 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new InternalSessionRequest( 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback(this, &SessionService::OnGotSessionCommands), 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback), consumer); 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionService::Handle SessionService::GetCurrentSession( 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CancelableRequestConsumerBase* consumer, 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCallback* callback) { 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pending_window_close_ids_.empty()) { 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If there are no pending window closes, we can get the current session 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from memory. 420513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<InternalSessionRequest> request(new InternalSessionRequest( 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback(this, &SessionService::OnGotSessionCommands), 422513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch callback)); 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRequest(request, consumer); 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IdToRange tab_to_available_range; 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<SessionID::id_type> windows_to_track; 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BuildCommandsFromBrowsers(&(request->commands), 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &tab_to_available_range, 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &windows_to_track); 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult( 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseSessionService::InternalGetCommandsRequest::TupleType( 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->handle(), request)); 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return request->handle(); 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If there are pending window closes, read the current session from disk. 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ScheduleGetCurrentSessionCommands( 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new InternalSessionRequest( 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewCallback(this, &SessionService::OnGotSessionCommands), 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback), consumer); 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::Save() { 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool had_commands = !pending_commands().empty(); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseSessionService::Save(); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (had_commands) { 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordSessionUpdateHistogramData(NotificationType::SESSION_SERVICE_SAVED, 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &last_updated_save_time_); 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::current()->Notify( 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::SESSION_SERVICE_SAVED, 450731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Source<Profile>(profile()), 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::NoDetails()); 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::Init() { 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Register for the notifications we're interested in. 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::TAB_PARENTED, 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::TAB_CLOSED, 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::NAV_LIST_PRUNED, 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::NAV_ENTRY_CHANGED, 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::BROWSER_OPENED, 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED, 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open, 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser) { 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!has_open_trackable_browsers_ && !BrowserInit::InProcessStartup() && 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !SessionRestore::IsRestoring() 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX) 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OSX has a fairly different idea of application lifetime than the 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // other platforms. We need to check that we aren't opening a window 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from the dock or the menubar. 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch && !app_controller_mac::IsOpeningNewWindow() 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ) { 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We're going from no tabbed browsers to a tabbed browser (and not in 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // process startup), restore the last session. 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (move_on_new_browser_) { 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make the current session the last. 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MoveCurrentSessionToLastSession(); 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch move_on_new_browser_ = false; 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionStartupPref pref = SessionStartupPref::GetStartupPref(profile()); 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pref.type == SessionStartupPref::LAST) { 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionRestore::RestoreSession( 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile(), browser, false, browser ? false : true, urls_to_open); 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::Observe(NotificationType type, 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // All of our messages have the NavigationController as the source. 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (type.value) { 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::BROWSER_OPENED: { 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = Source<Browser>(source).ptr(); 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser->profile() != profile() || 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !should_track_changes_for_browser_type(browser->type())) { 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RestoreIfNecessary(std::vector<GURL>(), browser); 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetWindowType(browser->session_id(), browser->type()); 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::TAB_PARENTED: { 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController* controller = 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(source).ptr(); 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetTabWindow(controller->window_id(), controller->session_id()); 523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContentsWrapper* wrapper = 524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContentsWrapper::GetCurrentWrapperForContents( 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen controller->tab_contents()); 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (wrapper->extension_tab_helper()->extension_app()) { 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetTabExtensionAppID( 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->window_id(), 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->session_id(), 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wrapper->extension_tab_helper()->extension_app()->id()); 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::TAB_CLOSED: { 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController* controller = 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(source).ptr(); 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabClosed(controller->window_id(), controller->session_id(), 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->tab_contents()->closed_by_user_gesture()); 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordSessionUpdateHistogramData(NotificationType::TAB_CLOSED, 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &last_updated_tab_closed_time_); 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::NAV_LIST_PRUNED: { 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController* controller = 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(source).ptr(); 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Details<NavigationController::PrunedDetails> pruned_details(details); 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pruned_details->from_front) { 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabNavigationPathPrunedFromFront(controller->window_id(), 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->session_id(), 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pruned_details->count); 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabNavigationPathPrunedFromBack(controller->window_id(), 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->session_id(), 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->entry_count()); 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordSessionUpdateHistogramData(NotificationType::NAV_LIST_PRUNED, 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &last_updated_nav_list_pruned_time_); 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::NAV_ENTRY_CHANGED: { 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController* controller = 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(source).ptr(); 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Details<NavigationController::EntryChangedDetails> changed(details); 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateTabNavigation(controller->window_id(), controller->session_id(), 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed->index, *changed->changed_entry); 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::NAV_ENTRY_COMMITTED: { 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController* controller = 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(source).ptr(); 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int current_entry_index = controller->GetCurrentEntryIndex(); 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectedNavigationIndex(controller->window_id(), 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->session_id(), 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_entry_index); 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateTabNavigation(controller->window_id(), controller->session_id(), 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_entry_index, 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *controller->GetEntryAtIndex(current_entry_index)); 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Details<NavigationController::LoadCommittedDetails> changed(details); 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (changed->type == NavigationType::NEW_PAGE || 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed->type == NavigationType::EXISTING_PAGE) { 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordSessionUpdateHistogramData(NotificationType::NAV_ENTRY_COMMITTED, 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &last_updated_nav_entry_commit_time_); 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED: { 592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtensionTabHelper* extension_tab_helper = 593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Source<ExtensionTabHelper>(source).ptr(); 594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (extension_tab_helper->extension_app()) { 595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetTabExtensionAppID( 596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen extension_tab_helper->tab_contents()->controller().window_id(), 597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen extension_tab_helper->tab_contents()->controller().session_id(), 598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen extension_tab_helper->extension_app()->id()); 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::SetTabExtensionAppID( 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& window_id, 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& extension_app_id) { 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldTrackChangesToWindow(window_id)) 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateSetTabExtensionAppIDCommand( 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCommandSetExtensionAppID, 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_id.id(), 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch extension_app_id)); 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionCommand* SessionService::CreateSetSelectedTabInWindow( 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& window_id, 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectedTabInIndexPayload payload = { 0 }; 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.id = window_id.id(); 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.index = index; 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = new SessionCommand(kCommandSetSelectedTabInIndex, 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(payload)); 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command; 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionCommand* SessionService::CreateSetTabWindowCommand( 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& window_id, 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id) { 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type payload[] = { window_id.id(), tab_id.id() }; 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new SessionCommand(kCommandSetTabWindow, sizeof(payload)); 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), payload, sizeof(payload)); 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command; 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionCommand* SessionService::CreateSetWindowBoundsCommand( 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& window_id, 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Rect& bounds, 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_maximized) { 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowBoundsPayload2 payload = { 0 }; 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.window_id = window_id.id(); 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.x = bounds.x(); 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.y = bounds.y(); 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.w = bounds.width(); 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.h = bounds.height(); 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.is_maximized = is_maximized; 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = new SessionCommand(kCommandSetWindowBounds2, 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(payload)); 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command; 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionCommand* SessionService::CreateSetTabIndexInWindowCommand( 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_index) { 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabIndexInWindowPayload payload = { 0 }; 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.id = tab_id.id(); 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.index = new_index; 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new SessionCommand(kCommandSetTabIndexInWindow, sizeof(payload)); 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command; 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionCommand* SessionService::CreateTabClosedCommand( 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID::id_type tab_id) { 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClosedPayload payload; 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Because of what appears to be a compiler bug setting payload to {0} doesn't 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // set the padding to 0, resulting in Purify reporting an UMR when we write 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the structure to disk. To avoid this we explicitly memset the struct. 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memset(&payload, 0, sizeof(payload)); 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.id = tab_id; 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.close_time = Time::Now().ToInternalValue(); 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new SessionCommand(kCommandTabClosed, sizeof(payload)); 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command; 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionCommand* SessionService::CreateWindowClosedCommand( 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID::id_type window_id) { 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClosedPayload payload; 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See comment in CreateTabClosedCommand as to why we do this. 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memset(&payload, 0, sizeof(payload)); 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.id = window_id; 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.close_time = Time::Now().ToInternalValue(); 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new SessionCommand(kCommandWindowClosed, sizeof(payload)); 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command; 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionCommand* SessionService::CreateSetSelectedNavigationIndexCommand( 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectedNavigationIndexPayload payload = { 0 }; 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.id = tab_id.id(); 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.index = index; 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = new SessionCommand( 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCommandSetSelectedNavigationIndex, sizeof(payload)); 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command; 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionCommand* SessionService::CreateSetWindowTypeCommand( 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& window_id, 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowType type) { 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowTypePayload payload = { 0 }; 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.id = window_id.id(); 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.index = static_cast<int32>(type); 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = new SessionCommand( 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCommandSetWindowType, sizeof(payload)); 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command; 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionCommand* SessionService::CreatePinnedStateCommand( 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& tab_id, 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_pinned) { 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PinnedStatePayload payload = { 0 }; 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.tab_id = tab_id.id(); 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.pinned_state = is_pinned; 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* command = 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new SessionCommand(kCommandSetPinnedState, sizeof(payload)); 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(command->contents(), &payload, sizeof(payload)); 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command; 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::OnGotSessionCommands( 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Handle handle, 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<InternalGetCommandsRequest> request) { 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedVector<SessionWindow> valid_windows; 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RestoreSessionFromCommands( 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->commands, &(valid_windows.get())); 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<InternalSessionRequest*>(request.get())-> 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch real_callback->RunWithParams( 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCallback::TupleType(request->handle(), 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &(valid_windows.get()))); 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::RestoreSessionFromCommands( 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<SessionCommand*>& commands, 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SessionWindow*>* valid_windows) { 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionTab*> tabs; 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionWindow*> windows; 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CreateTabsAndWindows(commands, &tabs, &windows)) { 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddTabsToWindows(&tabs, &windows); 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows); 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateSelectedTabIndex(valid_windows); 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STLDeleteValues(&tabs); 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't delete conents of windows, that is done by the caller as all 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // valid windows are added to valid_windows. 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::UpdateSelectedTabIndex( 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SessionWindow*>* windows) { 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<SessionWindow*>::const_iterator i = windows->begin(); 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != windows->end(); ++i) { 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See note in SessionWindow as to why we do this. 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_index = 0; 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<SessionTab*>::const_iterator j = (*i)->tabs.begin(); 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch j != (*i)->tabs.end(); ++j) { 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((*j)->tab_visual_index == (*i)->selected_tab_index) { 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_index = static_cast<int>(j - (*i)->tabs.begin()); 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*i)->selected_tab_index = new_index; 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionWindow* SessionService::GetWindow( 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type window_id, 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IdToSessionWindow* windows) { 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionWindow*>::iterator i = windows->find(window_id); 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i == windows->end()) { 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionWindow* window = new SessionWindow(); 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window->window_id.set_id(window_id); 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*windows)[window_id] = window; 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return window; 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return i->second; 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionTab* SessionService::GetTab( 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type tab_id, 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IdToSessionTab* tabs) { 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(tabs); 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionTab*>::iterator i = tabs->find(tab_id); 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i == tabs->end()) { 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionTab* tab = new SessionTab(); 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->tab_id.set_id(tab_id); 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*tabs)[tab_id] = tab; 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tab; 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return i->second; 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<TabNavigation>::iterator 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionService::FindClosestNavigationWithIndex( 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<TabNavigation>* navigations, 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(navigations); 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<TabNavigation>::iterator i = navigations->begin(); 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != navigations->end(); ++i) { 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i->index() >= index) 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return i; 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return navigations->end(); 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Function used in sorting windows. Sorting is done based on window id. As 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// window ids increment for each new window, this effectively sorts by creation 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// time. 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool WindowOrderSortFunction(const SessionWindow* w1, 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionWindow* w2) { 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return w1->window_id.id() < w2->window_id.id(); 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Compares the two tabs based on visual index. 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool TabVisualIndexSortFunction(const SessionTab* t1, 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionTab* t2) { 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int delta = t1->tab_visual_index - t2->tab_visual_index; 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return delta == 0 ? (t1->tab_id.id() < t2->tab_id.id()) : (delta < 0); 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::SortTabsBasedOnVisualOrderAndPrune( 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionWindow*>* windows, 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SessionWindow*>* valid_windows) { 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionWindow*>::iterator i = windows->begin(); 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (i != windows->end()) { 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i->second->tabs.empty() || i->second->is_constrained || 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !should_track_changes_for_browser_type( 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<Browser::Type>(i->second->type))) { 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete i->second; 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch windows->erase(i++); 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Valid window; sort the tabs and add it to the list of valid windows. 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::sort(i->second->tabs.begin(), i->second->tabs.end(), 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &TabVisualIndexSortFunction); 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add the window such that older windows appear first. 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (valid_windows->empty()) { 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch valid_windows->push_back(i->second); 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch valid_windows->insert( 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::upper_bound(valid_windows->begin(), valid_windows->end(), 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i->second, &WindowOrderSortFunction), 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i->second); 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++i; 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::AddTabsToWindows(std::map<int, SessionTab*>* tabs, 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionWindow*>* windows) { 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionTab*>::iterator i = tabs->begin(); 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (i != tabs->end()) { 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionTab* tab = i->second; 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab->window_id.id() && !tab->navigations.empty()) { 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionWindow* window = GetWindow(tab->window_id.id(), windows); 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window->tabs.push_back(tab); 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tabs->erase(i++); 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See note in SessionTab as to why we do this. 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<TabNavigation>::iterator j = 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FindClosestNavigationWithIndex(&(tab->navigations), 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->current_navigation_index); 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (j == tab->navigations.end()) { 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->current_navigation_index = 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(tab->navigations.size() - 1); 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->current_navigation_index = 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(j - tab->navigations.begin()); 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Never got a set tab index in window, or tabs are empty, nothing 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to do. 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++i; 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SessionService::CreateTabsAndWindows( 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<SessionCommand*>& data, 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionTab*>* tabs, 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<int, SessionWindow*>* windows) { 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the file is corrupt (command with wrong size, or unknown command), we 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // still return true and attempt to restore what we we can. 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<SessionCommand*>::const_iterator i = data.begin(); 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != data.end(); ++i) { 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionCommand* command = *i; 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (command->id()) { 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandSetTabWindow: { 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type payload[2]; 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(payload, sizeof(payload))) 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetTab(payload[1], tabs)->window_id.set_id(payload[0]); 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandSetWindowBounds2: { 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowBoundsPayload2 payload; 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(&payload, sizeof(payload))) 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetWindow(payload.window_id, windows)->bounds.SetRect(payload.x, 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.y, 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.w, 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.h); 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetWindow(payload.window_id, windows)->is_maximized = 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.is_maximized; 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandSetTabIndexInWindow: { 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabIndexInWindowPayload payload; 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(&payload, sizeof(payload))) 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetTab(payload.id, tabs)->tab_visual_index = payload.index; 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandTabClosed: 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandWindowClosed: { 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClosedPayload payload; 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(&payload, sizeof(payload))) 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (command->id() == kCommandTabClosed) { 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete GetTab(payload.id, tabs); 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tabs->erase(payload.id); 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete GetWindow(payload.id, windows); 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch windows->erase(payload.id); 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandTabNavigationPathPrunedFromBack: { 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabNavigationPathPrunedFromBackPayload payload; 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(&payload, sizeof(payload))) 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionTab* tab = GetTab(payload.id, tabs); 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->navigations.erase( 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FindClosestNavigationWithIndex(&(tab->navigations), payload.index), 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->navigations.end()); 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandTabNavigationPathPrunedFromFront: { 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabNavigationPathPrunedFromFrontPayload payload; 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(&payload, sizeof(payload)) || 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch payload.index <= 0) { 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionTab* tab = GetTab(payload.id, tabs); 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the selected navigation index. 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->current_navigation_index = 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(-1, tab->current_navigation_index - payload.index); 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // And update the index of existing navigations. 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<TabNavigation>::iterator i = tab->navigations.begin(); 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != tab->navigations.end();) { 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i->set_index(i->index() - payload.index); 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i->index() < 0) 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i = tab->navigations.erase(i); 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++i; 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandUpdateTabNavigation: { 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabNavigation navigation; 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type tab_id; 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!RestoreUpdateTabNavigationCommand(*command, &navigation, &tab_id)) 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionTab* tab = GetTab(tab_id, tabs); 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<TabNavigation>::iterator i = 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FindClosestNavigationWithIndex(&(tab->navigations), 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch navigation.index()); 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i != tab->navigations.end() && i->index() == navigation.index()) 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *i = navigation; 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->navigations.insert(i, navigation); 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandSetSelectedNavigationIndex: { 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectedNavigationIndexPayload payload; 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(&payload, sizeof(payload))) 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetTab(payload.id, tabs)->current_navigation_index = payload.index; 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandSetSelectedTabInIndex: { 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectedTabInIndexPayload payload; 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(&payload, sizeof(payload))) 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetWindow(payload.id, windows)->selected_tab_index = payload.index; 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandSetWindowType: { 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowTypePayload payload; 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(&payload, sizeof(payload))) 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetWindow(payload.id, windows)->is_constrained = false; 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetWindow(payload.id, windows)->type = 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserTypeForWindowType( 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<WindowType>(payload.index)); 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandSetPinnedState: { 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PinnedStatePayload payload; 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command->GetPayload(&payload, sizeof(payload))) 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetTab(payload.tab_id, tabs)->pinned = payload.pinned_state; 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case kCommandSetExtensionAppID: { 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type tab_id; 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string extension_app_id; 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!RestoreSetTabExtensionAppIDCommand( 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *command, &tab_id, &extension_app_id)) { 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetTab(tab_id, tabs)->extension_app_id.swap(extension_app_id); 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::BuildCommandsForTab( 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID& window_id, 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController* controller, 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index_in_window, 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_pinned, 1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SessionCommand*>* commands, 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IdToRange* tab_to_available_range) { 1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(controller && commands && window_id.id()); 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands->push_back( 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateSetTabWindowCommand(window_id, controller->session_id())); 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int current_index = controller->GetCurrentEntryIndex(); 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int min_index = std::max(0, 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_index - max_persist_navigation_count); 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int max_index = std::min(current_index + max_persist_navigation_count, 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->entry_count()); 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int pending_index = controller->pending_entry_index(); 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_to_available_range) { 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*tab_to_available_range)[controller->session_id().id()] = 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::pair<int, int>(min_index, max_index); 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (is_pinned) { 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands->push_back( 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreatePinnedStateCommand(controller->session_id(), true)); 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1081ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContentsWrapper* wrapper = 1082ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContentsWrapper::GetCurrentWrapperForContents( 1083ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen controller->tab_contents()); 1084ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (wrapper->extension_tab_helper()->extension_app()) { 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands->push_back( 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateSetTabExtensionAppIDCommand( 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCommandSetExtensionAppID, 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->session_id().id(), 1089ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wrapper->extension_tab_helper()->extension_app()->id())); 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = min_index; i < max_index; ++i) { 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NavigationEntry* entry = (i == pending_index) ? 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->pending_entry() : controller->GetEntryAtIndex(i); 1094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(entry); 1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ShouldTrackEntry(*entry)) { 1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands->push_back( 1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateUpdateTabNavigationCommand(kCommandUpdateTabNavigation, 1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->session_id().id(), 1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i, 1100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *entry)); 1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands->push_back( 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateSetSelectedNavigationIndexCommand(controller->session_id(), 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_index)); 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index_in_window != -1) { 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands->push_back( 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateSetTabIndexInWindowCommand(controller->session_id(), 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index_in_window)); 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::BuildCommandsForBrowser( 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser, 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SessionCommand*>* commands, 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IdToRange* tab_to_available_range, 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<SessionID::id_type>* windows_to_track) { 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser && commands); 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser->session_id().id()); 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands->push_back( 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateSetWindowBoundsCommand(browser->session_id(), 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->window()->GetRestoredBounds(), 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->window()->IsMaximized())); 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands->push_back(CreateSetWindowTypeCommand( 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->session_id(), WindowTypeForBrowserType(browser->type()))); 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool added_to_windows_to_track = false; 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < browser->tab_count(); ++i) { 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* tab = browser->GetTabContentsAt(i); 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(tab); 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab->profile() == profile() || profile() == NULL) { 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BuildCommandsForTab(browser->session_id(), &tab->controller(), i, 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->tabstrip_model()->IsTabPinned(i), 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands, tab_to_available_range); 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (windows_to_track && !added_to_windows_to_track) { 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch windows_to_track->insert(browser->session_id().id()); 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch added_to_windows_to_track = true; 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands->push_back( 1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateSetSelectedTabInWindow(browser->session_id(), 1146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser->active_index())); 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::BuildCommandsFromBrowsers( 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SessionCommand*>* commands, 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IdToRange* tab_to_available_range, 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<SessionID::id_type>* windows_to_track) { 1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(commands); 1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator i = BrowserList::begin(); 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != BrowserList::end(); ++i) { 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure the browser has tabs and a window. Browsers destructor 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // removes itself from the BrowserList. When a browser is closed the 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // destructor is not necessarily run immediately. This means its possible 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for us to get a handle to a browser that is about to be removed. If 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the tab count is 0 or the window is NULL, the browser is about to be 1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // deleted, so we ignore it. 1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (should_track_changes_for_browser_type((*i)->type()) && 1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*i)->tab_count() && (*i)->window()) { 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BuildCommandsForBrowser(*i, commands, tab_to_available_range, 1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch windows_to_track); 1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::ScheduleReset() { 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_pending_reset(true); 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STLDeleteElements(&pending_commands()); 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_to_available_range_.clear(); 1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch windows_tracking_.clear(); 1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BuildCommandsFromBrowsers(&pending_commands(), &tab_to_available_range_, 1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &windows_tracking_); 1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!windows_tracking_.empty()) { 1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We're lazily created on startup and won't get an initial batch of 1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SetWindowType messages. Set these here to make sure our state is correct. 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_open_trackable_browsers_ = true; 1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch move_on_new_browser_ = true; 1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartSaveTimer(); 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SessionService::ReplacePendingCommand(SessionCommand* command) { 1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We only optimize page navigations, which can happen quite frequently and 1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // are expensive. If necessary, other commands could be searched for as 1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // well. 1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (command->id() != kCommandUpdateTabNavigation) 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void* iterator = NULL; 1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle()); 1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type command_tab_id; 1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int command_nav_index; 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!command_pickle->ReadInt(&iterator, &command_tab_id) || 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !command_pickle->ReadInt(&iterator, &command_nav_index)) { 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<SessionCommand*>::reverse_iterator i = 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_commands().rbegin(); i != pending_commands().rend(); ++i) { 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionCommand* existing_command = *i; 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (existing_command->id() == kCommandUpdateTabNavigation) { 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionID::id_type existing_tab_id; 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int existing_nav_index; 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creating a pickle like this means the Pickle references the data from 1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the command. Make sure we delete the pickle before the command, else 1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the pickle references deleted memory. 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<Pickle> existing_pickle(existing_command->PayloadAsPickle()); 1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iterator = NULL; 1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!existing_pickle->ReadInt(&iterator, &existing_tab_id) || 1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !existing_pickle->ReadInt(&iterator, &existing_nav_index)) { 1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (existing_tab_id == command_tab_id && 1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch existing_nav_index == command_nav_index) { 1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // existing_command is an update for the same tab/index pair. Replace 1220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it with the new one. We need to add to the end of the list just in 1221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // case there is a prune command after the update command. 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete existing_command; 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_commands().erase(i.base() - 1); 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_commands().push_back(command); 1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::ScheduleCommand(SessionCommand* command) { 1234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(command); 1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ReplacePendingCommand(command)) 1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseSessionService::ScheduleCommand(command); 1238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't schedule a reset on tab closed/window closed. Otherwise we may 1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // lose tabs/windows we want to restore from if we exit right after this. 1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pending_reset() && pending_window_close_ids_.empty() && 1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commands_since_reset() >= kWritesPerReset && 1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (command->id() != kCommandTabClosed && 1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch command->id() != kCommandWindowClosed)) { 1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleReset(); 1245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::CommitPendingCloses() { 1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (PendingTabCloseIDs::iterator i = pending_tab_close_ids_.begin(); 1250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != pending_tab_close_ids_.end(); ++i) { 1251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateTabClosedCommand(*i)); 1252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_tab_close_ids_.clear(); 1254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (PendingWindowCloseIDs::iterator i = pending_window_close_ids_.begin(); 1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != pending_window_close_ids_.end(); ++i) { 1257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommand(CreateWindowClosedCommand(*i)); 1258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_window_close_ids_.clear(); 1260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SessionService::IsOnlyOneTabLeft() { 1263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!profile()) { 1264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We're testing, always return false. 1265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_count = 0; 1269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator i = BrowserList::begin(); 1270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != BrowserList::end(); ++i) { 1271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID::id_type window_id = (*i)->session_id().id(); 1272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (should_track_changes_for_browser_type((*i)->type()) && 1273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (*i)->profile() == profile() && 1274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_closing_ids_.find(window_id) == window_closing_ids_.end()) { 1275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (++window_count > 1) 1276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // By the time this is invoked the tab has been removed. As such, we use 1278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // > 0 here rather than > 1. 1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((*i)->tab_count() > 0) 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SessionService::HasOpenTrackableBrowsers(const SessionID& window_id) { 1287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!profile()) { 1288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We're testing, always return false. 1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator i = BrowserList::begin(); 1293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != BrowserList::end(); ++i) { 1294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = *i; 1295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SessionID::id_type browser_id = browser->session_id().id(); 1296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser_id != window_id.id() && 1297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_closing_ids_.find(browser_id) == window_closing_ids_.end() && 1298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch should_track_changes_for_browser_type(browser->type()) && 1299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser->profile() == profile()) { 1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SessionService::ShouldTrackChangesToWindow(const SessionID& window_id) { 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return windows_tracking_.find(window_id.id()) != windows_tracking_.end(); 1308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1311c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSessionService::WindowType SessionService::WindowTypeForBrowserType( 1312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser::Type type) { 1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't support masks here, only discrete types. 1314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (type) { 1315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case Browser::TYPE_POPUP: 1316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TYPE_POPUP; 1317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case Browser::TYPE_APP: 1318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TYPE_APP; 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case Browser::TYPE_APP_POPUP: 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TYPE_APP_POPUP; 1321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case Browser::TYPE_DEVTOOLS: 1322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TYPE_DEVTOOLS; 1323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case Browser::TYPE_APP_PANEL: 1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TYPE_APP_PANEL; 1325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case Browser::TYPE_NORMAL: 1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TYPE_NORMAL; 1328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1331c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowser::Type SessionService::BrowserTypeForWindowType( 1332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionService::WindowType type) { 1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (type) { 1334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case TYPE_POPUP: 1335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return Browser::TYPE_POPUP; 1336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case TYPE_APP: 1337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return Browser::TYPE_APP; 1338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case TYPE_APP_POPUP: 1339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return Browser::TYPE_APP_POPUP; 1340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case TYPE_DEVTOOLS: 1341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return Browser::TYPE_DEVTOOLS; 1342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case TYPE_APP_PANEL: 1343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return Browser::TYPE_APP_PANEL; 1344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case TYPE_NORMAL: 1345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return Browser::TYPE_NORMAL; 1347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::RecordSessionUpdateHistogramData(NotificationType type, 1351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks* last_updated_time) { 1352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!last_updated_time->is_null()) { 1353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta delta = base::TimeTicks::Now() - *last_updated_time; 1354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We're interested in frequent updates periods longer than 1355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 10 minutes. 1356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_long_period = false; 1357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delta >= save_delay_in_mins_) { 1358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch use_long_period = true; 1359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (type.value) { 1361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::SESSION_SERVICE_SAVED : 1362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordUpdatedSaveTime(delta, use_long_period); 1363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordUpdatedSessionNavigationOrTab(delta, use_long_period); 1364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::TAB_CLOSED: 1366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordUpdatedTabClosed(delta, use_long_period); 1367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordUpdatedSessionNavigationOrTab(delta, use_long_period); 1368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::NAV_LIST_PRUNED: 1370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordUpdatedNavListPruned(delta, use_long_period); 1371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordUpdatedSessionNavigationOrTab(delta, use_long_period); 1372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::NAV_ENTRY_COMMITTED: 1374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordUpdatedNavEntryCommit(delta, use_long_period); 1375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordUpdatedSessionNavigationOrTab(delta, use_long_period); 1376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Bad type sent to RecordSessionUpdateHistogramData"; 1379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*last_updated_time) = base::TimeTicks::Now(); 1383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::RecordUpdatedTabClosed(base::TimeDelta delta, 1386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_long_period) { 1387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string name("SessionRestore.TabClosedPeriod"); 1388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(name, 1389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2500ms is the default save delay. 1391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_millis_, 1392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (use_long_period) { 1395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string long_name_("SessionRestore.TabClosedLongPeriod"); 1396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, 1397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_hrs_, 1400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::RecordUpdatedNavListPruned(base::TimeDelta delta, 1405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_long_period) { 1406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string name("SessionRestore.NavigationListPrunedPeriod"); 1407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(name, 1408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2500ms is the default save delay. 1410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_millis_, 1411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (use_long_period) { 1414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string long_name_("SessionRestore.NavigationListPrunedLongPeriod"); 1415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, 1416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_hrs_, 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::RecordUpdatedNavEntryCommit(base::TimeDelta delta, 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_long_period) { 1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string name("SessionRestore.NavEntryCommittedPeriod"); 1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(name, 1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2500ms is the default save delay. 1429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_millis_, 1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (use_long_period) { 1433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string long_name_("SessionRestore.NavEntryCommittedLongPeriod"); 1434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, 1435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_hrs_, 1438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::RecordUpdatedSessionNavigationOrTab(base::TimeDelta delta, 1443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_long_period) { 1444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string name("SessionRestore.NavOrTabUpdatePeriod"); 1445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(name, 1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2500ms is the default save delay. 1448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_millis_, 1449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (use_long_period) { 1452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string long_name_("SessionRestore.NavOrTabUpdateLongPeriod"); 1453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, 1454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_hrs_, 1457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SessionService::RecordUpdatedSaveTime(base::TimeDelta delta, 1462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_long_period) { 1463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string name("SessionRestore.SavePeriod"); 1464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(name, 1465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2500ms is the default save delay. 1467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_millis_, 1468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (use_long_period) { 1471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string long_name_("SessionRestore.SaveLongPeriod"); 1472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, 1473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delta, 1474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_mins_, 1475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_delay_in_hrs_, 1476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50); 1477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1479