tab_restore_service_helper.cc revision 3240926e260ce088908e02ac07a6cf7b0c0cbf44
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service_helper.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iterator>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_types.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service_delegate.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service_observer.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/session_storage_namespace.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#if !defined(OS_ANDROID)
28558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
29558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#endif
30558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecordAppLaunch(Profile* profile, const TabRestoreService::Tab& tab) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url = tab.navigations.at(tab.current_navigation_index).virtual_url();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile->GetExtensionService());
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const extensions::Extension* extension =
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile->GetExtensionService()->GetInstalledApp(url);
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!extension)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  CoreAppLauncherHandler::RecordAppLaunchType(
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension_misc::APP_LAUNCH_NTP_RECENTLY_CLOSED,
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension->GetType());
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_ANDROID)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabRestoreServiceHelper::Observer -------------------------------------------
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabRestoreServiceHelper::Observer::~Observer() {}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::Observer::OnClearEntries() {}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::Observer::OnRestoreEntryById(
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type id,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Entries::const_iterator entry_iterator) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::Observer::OnAddEntry() {}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabRestoreServiceHelper -----------------------------------------------------
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabRestoreServiceHelper::TabRestoreServiceHelper(
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreService* tab_restore_service,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Observer* observer,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreService::TimeFactory* time_factory)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : tab_restore_service_(tab_restore_service),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_(observer),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(profile),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restoring_(false),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      time_factory_(time_factory) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(tab_restore_service_);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabRestoreServiceHelper::~TabRestoreServiceHelper() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    TabRestoreServiceDestroyed(tab_restore_service_));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&entries_);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::AddObserver(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreServiceObserver* observer) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_list_.AddObserver(observer);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::RemoveObserver(
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreServiceObserver* observer) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_list_.RemoveObserver(observer);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::CreateHistoricalTab(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::WebContents* contents,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (restoring_)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabRestoreServiceDelegate* delegate =
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TabRestoreServiceDelegate::FindDelegateForWebContents(contents);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (closing_delegates_.find(delegate) != closing_delegates_.end())
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Tab> local_tab(new Tab());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PopulateTab(local_tab.get(), index, delegate, &contents->GetController());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (local_tab->navigations.empty())
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddEntry(local_tab.release(), true, true);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::BrowserClosing(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreServiceDelegate* delegate) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  closing_delegates_.insert(delegate);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> window(new Window());
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->selected_tab_index = delegate->GetSelectedIndex();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->timestamp = TimeNow();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->app_name = delegate->GetAppName();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't use std::vector::resize() because it will push copies of an empty tab
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // into the vector, which will give all tabs in a window the same ID.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < delegate->GetTabCount(); ++i) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->tabs.push_back(Tab());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t entry_index = 0;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int tab_index = 0; tab_index < delegate->GetTabCount(); ++tab_index) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PopulateTab(&(window->tabs[entry_index]),
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                tab_index,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                delegate,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &delegate->GetWebContentsAt(tab_index)->GetController());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window->tabs[entry_index].navigations.empty()) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window->tabs.erase(window->tabs.begin() + entry_index);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window->tabs[entry_index].browser_id = delegate->GetSessionID().id();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry_index++;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window->tabs.size() == 1 && window->app_name.empty()) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Short-circuit creating a Window if only 1 tab was present. This fixes
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // http://crbug.com/56744. Copy the Tab because it's owned by an object on
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the stack.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddEntry(new Tab(window->tabs[0]), true, true);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!window->tabs.empty()) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->selected_tab_index =
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(static_cast<int>(window->tabs.size() - 1),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 window->selected_tab_index);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddEntry(window.release(), true, true);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::BrowserClosed(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreServiceDelegate* delegate) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  closing_delegates_.erase(delegate);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::ClearEntries() {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnClearEntries();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&entries_);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyTabsChanged();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const TabRestoreService::Entries& TabRestoreServiceHelper::entries() const {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return entries_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::vector<content::WebContents*>
1743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochTabRestoreServiceHelper::RestoreMostRecentEntry(
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TabRestoreServiceDelegate* delegate,
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::HostDesktopType host_desktop_type) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entries_.empty())
1783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return std::vector<WebContents*>();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return RestoreEntryById(delegate, entries_.front()->id, host_desktop_type,
1813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      UNKNOWN);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabRestoreService::Tab* TabRestoreServiceHelper::RemoveTabEntryById(
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type id) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Entries::iterator i = GetEntryIteratorById(id);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == entries_.end())
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Entry* entry = *i;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->type != TabRestoreService::TAB)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tab* tab = static_cast<Tab*>(entry);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_.erase(i);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return tab;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::vector<content::WebContents*> TabRestoreServiceHelper::RestoreEntryById(
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreServiceDelegate* delegate,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionID::id_type id,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::HostDesktopType host_desktop_type,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WindowOpenDisposition disposition) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Entries::iterator entry_iterator = GetEntryIteratorById(id);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_iterator == entries_.end())
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't hoark here, we allow an invalid id.
2073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return std::vector<WebContents*>();
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnRestoreEntryById(id, entry_iterator);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  restoring_ = true;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Entry* entry = *entry_iterator;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the entry's ID does not match the ID that is being restored, then the
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // entry is a window from which a single tab will be restored.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool restoring_tab_in_window = entry->id != id;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!restoring_tab_in_window) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries_.erase(entry_iterator);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry_iterator = entries_.end();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |delegate| will be NULL in cases where one isn't already available (eg,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when invoked on Mac OS X with no windows open). In this case, create a
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // new browser into which we restore the tabs.
2263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  std::vector<WebContents*> web_contents;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->type == TabRestoreService::TAB) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tab* tab = static_cast<Tab*>(entry);
2293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    WebContents* restored_tab = NULL;
2303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    delegate = RestoreTab(*tab, delegate, host_desktop_type, disposition,
2313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        &restored_tab);
2323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    web_contents.push_back(restored_tab);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate->ShowBrowserWindow();
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (entry->type == TabRestoreService::WINDOW) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreServiceDelegate* current_delegate = delegate;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Window* window = static_cast<Window*>(entry);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When restoring a window, either the entire window can be restored, or a
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // single tab within it. If the entry's ID matches the one to restore, then
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the entire window will be restored.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!restoring_tab_in_window) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delegate = TabRestoreServiceDelegate::Create(profile_, host_desktop_type,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   window->app_name);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const Tab& tab = window->tabs[tab_i];
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebContents* restored_tab = delegate->AddRestoredTab(
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            tab.navigations,
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            delegate->GetTabCount(),
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            tab.current_navigation_index,
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            tab.extension_app_id,
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            static_cast<int>(tab_i) == window->selected_tab_index,
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            tab.pinned,
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            tab.from_last_session,
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            tab.session_storage_namespace.get(),
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            tab.user_agent_override);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (restored_tab) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          restored_tab->GetController().LoadIfNecessary();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          RecordAppLaunch(profile_, tab);
2593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          web_contents.push_back(restored_tab);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // All the window's tabs had the same former browser_id.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (window->tabs[0].has_browser()) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UpdateTabBrowserIDs(window->tabs[0].browser_id,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            delegate->GetSessionID().id());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Restore a single tab from the window. Find the tab that matches the ID
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // in the window and restore it.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (std::vector<Tab>::iterator tab_i = window->tabs.begin();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           tab_i != window->tabs.end(); ++tab_i) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const Tab& tab = *tab_i;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (tab.id == id) {
2743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          WebContents* restored_tab = NULL;
2753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          delegate = RestoreTab(tab, delegate, host_desktop_type, disposition,
2763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch              &restored_tab);
2773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          web_contents.push_back(restored_tab);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          window->tabs.erase(tab_i);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // If restoring the tab leaves the window with nothing else, delete it
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // as well.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!window->tabs.size()) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entries_.erase(entry_iterator);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            delete entry;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // Update the browser ID of the rest of the tabs in the window so if
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // any one is restored, it goes into the same window as the tab
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // being restored now.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            UpdateTabBrowserIDs(tab.browser_id,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                delegate->GetSessionID().id());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (std::vector<Tab>::iterator tab_j = window->tabs.begin();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 tab_j != window->tabs.end(); ++tab_j) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (*tab_j).browser_id = delegate->GetSessionID().id();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate->ShowBrowserWindow();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (disposition == CURRENT_TAB && current_delegate &&
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_delegate->GetActiveWebContents()) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_delegate->CloseTab();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!restoring_tab_in_window) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete entry;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  restoring_ = false;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyTabsChanged();
3153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return web_contents;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::NotifyTabsChanged() {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    TabRestoreServiceChanged(tab_restore_service_));
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
323a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void TabRestoreServiceHelper::NotifyLoaded() {
324a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_,
325a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                    TabRestoreServiceLoaded(tab_restore_service_));
326a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
327a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::AddEntry(Entry* entry,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool notify,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool to_front) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FilterEntry(entry) || (entries_.size() >= kMaxEntries && !to_front)) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete entry;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (to_front)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries_.push_front(entry);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries_.push_back(entry);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PruneEntries();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (notify)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyTabsChanged();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnAddEntry();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::PruneEntries() {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Entries new_entries;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TabRestoreService::Entries::const_iterator iter = entries_.begin();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != entries_.end(); ++iter) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreService::Entry* entry = *iter;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FilterEntry(entry) &&
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_entries.size() < kMaxEntries) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_entries.push_back(entry);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete entry;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_ = new_entries;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabRestoreService::Entries::iterator
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*i)->id == id)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For Window entries, see if the ID matches a tab. If so, report the window
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // as the Entry.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*i)->type == TabRestoreService::WINDOW) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<Tab>& tabs = static_cast<Window*>(*i)->tabs;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (std::vector<Tab>::iterator j = tabs.begin();
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           j != tabs.end(); ++j) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((*j).id == id) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return i;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return entries_.end();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabRestoreServiceHelper::ValidateEntry(Entry* entry) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->type == TabRestoreService::TAB)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ValidateTab(static_cast<Tab*>(entry));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->type == TabRestoreService::WINDOW)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ValidateWindow(static_cast<Window*>(entry));
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::PopulateTab(
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tab* tab,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreServiceDelegate* delegate,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NavigationController* controller) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int pending_index = controller->GetPendingEntryIndex();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int entry_count = controller->GetEntryCount();
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_count == 0 && pending_index == 0)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry_count++;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tab->navigations.resize(static_cast<int>(entry_count));
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < entry_count; ++i) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NavigationEntry* entry = (i == pending_index) ?
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        controller->GetPendingEntry() : controller->GetEntryAtIndex(i);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab->navigations[i] =
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sessions::SerializedNavigationEntry::FromNavigationEntry(i, *entry);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tab->timestamp = TimeNow();
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tab->current_navigation_index = controller->GetCurrentEntryIndex();
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab->current_navigation_index == -1 && entry_count > 0)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab->current_navigation_index = 0;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tab->tabstrip_index = index;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extensions::TabHelper* extensions_tab_helper =
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::TabHelper::FromWebContents(controller->GetWebContents());
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // extensions_tab_helper is NULL in some browser tests.
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (extensions_tab_helper) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const extensions::Extension* extension =
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extensions_tab_helper->extension_app();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab->extension_app_id = extension->id();
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tab->user_agent_override =
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controller->GetWebContents()->GetUserAgentOverride();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // TODO(ajwong): This does not correctly handle storage for isolated apps.
437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  tab->session_storage_namespace =
438ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      controller->GetDefaultSessionStorageNamespace();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delegate may be NULL during unit tests.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab->browser_id = delegate->GetSessionID().id();
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab->pinned = delegate->IsTabPinned(tab->tabstrip_index);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabRestoreServiceDelegate* TabRestoreServiceHelper::RestoreTab(
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Tab& tab,
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabRestoreServiceDelegate* delegate,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::HostDesktopType host_desktop_type,
4513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    WindowOpenDisposition disposition,
4523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    WebContents** contents) {
4533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  WebContents* web_contents;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disposition == CURRENT_TAB && delegate) {
4553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    web_contents = delegate->ReplaceRestoredTab(
4563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        tab.navigations,
4573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        tab.current_navigation_index,
4583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        tab.from_last_session,
4593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        tab.extension_app_id,
4603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        tab.session_storage_namespace.get(),
4613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        tab.user_agent_override);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We only respsect the tab's original browser if there's no disposition.
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (disposition == UNKNOWN && tab.has_browser()) {
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delegate = TabRestoreServiceDelegate::FindDelegateWithID(
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     tab.browser_id, host_desktop_type);
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tab_index = -1;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |delegate| will be NULL in cases where one isn't already available (eg,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when invoked on Mac OS X with no windows open). In this case, create a
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // new browser into which we restore the tabs.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate && disposition != NEW_WINDOW) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_index = tab.tabstrip_index;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delegate = TabRestoreServiceDelegate::Create(profile_, host_desktop_type,
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   std::string());
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (tab.has_browser())
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UpdateTabBrowserIDs(tab.browser_id, delegate->GetSessionID().id());
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Place the tab at the end if the tab index is no longer valid or
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we were passed a specific disposition.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tab_index < 0 || tab_index > delegate->GetTabCount() ||
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        disposition != UNKNOWN) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_index = delegate->GetTabCount();
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    web_contents = delegate->AddRestoredTab(tab.navigations,
4913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                            tab_index,
4923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                            tab.current_navigation_index,
4933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                            tab.extension_app_id,
4943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                            disposition != NEW_BACKGROUND_TAB,
4953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                            tab.pinned,
4963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                            tab.from_last_session,
4973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                            tab.session_storage_namespace.get(),
4983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                            tab.user_agent_override);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_contents->GetController().LoadIfNecessary();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecordAppLaunch(profile_, tab);
5023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (contents)
5033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    *contents = web_contents;
5043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return delegate;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabRestoreServiceHelper::ValidateTab(Tab* tab) {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab->navigations.empty())
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tab->current_navigation_index =
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::max(0, std::min(tab->current_navigation_index,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           static_cast<int>(tab->navigations.size()) - 1));
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabRestoreServiceHelper::ValidateWindow(Window* window) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->selected_tab_index =
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::max(0, std::min(window->selected_tab_index,
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           static_cast<int>(window->tabs.size() - 1)));
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i = 0;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<Tab>::iterator tab_i = window->tabs.begin();
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       tab_i != window->tabs.end();) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ValidateTab(&(*tab_i))) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_i = window->tabs.erase(tab_i);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i < window->selected_tab_index)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window->selected_tab_index--;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (i == window->selected_tab_index)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window->selected_tab_index = 0;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++tab_i;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window->tabs.empty())
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabRestoreServiceHelper::IsTabInteresting(const Tab* tab) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab->navigations.empty())
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab->navigations.size() > 1)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return tab->pinned ||
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab->navigations.at(0).virtual_url() !=
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GURL(chrome::kChromeUINewTabURL);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabRestoreServiceHelper::IsWindowInteresting(const Window* window) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window->tabs.empty())
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window->tabs.size() > 1)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsTabInteresting(&window->tabs[0]);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabRestoreServiceHelper::FilterEntry(Entry* entry) {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ValidateEntry(entry))
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->type == TabRestoreService::TAB)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return IsTabInteresting(static_cast<Tab*>(entry));
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (entry->type == TabRestoreService::WINDOW)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return IsWindowInteresting(static_cast<Window*>(entry));
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabRestoreServiceHelper::UpdateTabBrowserIDs(SessionID::id_type old_id,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  SessionID::id_type new_id) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Entry* entry = *i;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry->type == TabRestoreService::TAB) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tab* tab = static_cast<Tab*>(entry);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (tab->browser_id == old_id)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tab->browser_id = new_id;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Time TabRestoreServiceHelper::TimeNow() const {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return time_factory_ ? time_factory_->TimeNow() : base::Time::Now();
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
596