Home | History | Annotate | Download | only in sessions
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/sessions/session_restore.h"
      6 
      7 #include <algorithm>
      8 #include <list>
      9 #include <set>
     10 #include <string>
     11 
     12 #include "base/bind.h"
     13 #include "base/bind_helpers.h"
     14 #include "base/callback.h"
     15 #include "base/command_line.h"
     16 #include "base/debug/alias.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/memory/scoped_vector.h"
     19 #include "base/metrics/histogram.h"
     20 #include "base/run_loop.h"
     21 #include "base/stl_util.h"
     22 #include "base/strings/stringprintf.h"
     23 #include "base/task/cancelable_task_tracker.h"
     24 #include "chrome/browser/browser_process.h"
     25 #include "chrome/browser/chrome_notification_types.h"
     26 #include "chrome/browser/performance_monitor/startup_timer.h"
     27 #include "chrome/browser/profiles/profile.h"
     28 #include "chrome/browser/search/search.h"
     29 #include "chrome/browser/sessions/session_service.h"
     30 #include "chrome/browser/sessions/session_service_factory.h"
     31 #include "chrome/browser/sessions/session_types.h"
     32 #include "chrome/browser/ui/browser.h"
     33 #include "chrome/browser/ui/browser_finder.h"
     34 #include "chrome/browser/ui/browser_navigator.h"
     35 #include "chrome/browser/ui/browser_tabrestore.h"
     36 #include "chrome/browser/ui/browser_tabstrip.h"
     37 #include "chrome/browser/ui/browser_window.h"
     38 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     39 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
     40 #include "chrome/common/url_constants.h"
     41 #include "content/public/browser/child_process_security_policy.h"
     42 #include "content/public/browser/dom_storage_context.h"
     43 #include "content/public/browser/navigation_controller.h"
     44 #include "content/public/browser/notification_registrar.h"
     45 #include "content/public/browser/notification_service.h"
     46 #include "content/public/browser/render_process_host.h"
     47 #include "content/public/browser/render_widget_host.h"
     48 #include "content/public/browser/render_widget_host_view.h"
     49 #include "content/public/browser/session_storage_namespace.h"
     50 #include "content/public/browser/storage_partition.h"
     51 #include "content/public/browser/web_contents.h"
     52 #include "extensions/browser/extension_registry.h"
     53 #include "extensions/common/extension_set.h"
     54 #include "net/base/network_change_notifier.h"
     55 
     56 #if defined(OS_CHROMEOS)
     57 #include "chrome/browser/chromeos/boot_times_loader.h"
     58 #endif
     59 
     60 using content::NavigationController;
     61 using content::RenderWidgetHost;
     62 using content::WebContents;
     63 
     64 namespace {
     65 
     66 class SessionRestoreImpl;
     67 class TabLoader;
     68 
     69 TabLoader* shared_tab_loader = NULL;
     70 
     71 // Pointers to SessionRestoreImpls which are currently restoring the session.
     72 std::set<SessionRestoreImpl*>* active_session_restorers = NULL;
     73 
     74 // TabLoader ------------------------------------------------------------------
     75 
     76 // Initial delay (see class decription for details).
     77 static const int kInitialDelayTimerMS = 100;
     78 
     79 // TabLoader is responsible for loading tabs after session restore creates
     80 // tabs. New tabs are loaded after the current tab finishes loading, or a delay
     81 // is reached (initially kInitialDelayTimerMS). If the delay is reached before
     82 // a tab finishes loading a new tab is loaded and the time of the delay
     83 // doubled.
     84 //
     85 // TabLoader keeps a reference to itself when it's loading. When it has finished
     86 // loading, it drops the reference. If another profile is restored while the
     87 // TabLoader is loading, it will schedule its tabs to get loaded by the same
     88 // TabLoader. When doing the scheduling, it holds a reference to the TabLoader.
     89 //
     90 // This is not part of SessionRestoreImpl so that synchronous destruction
     91 // of SessionRestoreImpl doesn't have timing problems.
     92 class TabLoader : public content::NotificationObserver,
     93                   public net::NetworkChangeNotifier::ConnectionTypeObserver,
     94                   public base::RefCounted<TabLoader> {
     95  public:
     96   // Retrieves a pointer to the TabLoader instance shared between profiles, or
     97   // creates a new TabLoader if it doesn't exist. If a TabLoader is created, its
     98   // starting timestamp is set to |restore_started|.
     99   static TabLoader* GetTabLoader(base::TimeTicks restore_started);
    100 
    101   // Schedules a tab for loading.
    102   void ScheduleLoad(NavigationController* controller);
    103 
    104   // Notifies the loader that a tab has been scheduled for loading through
    105   // some other mechanism.
    106   void TabIsLoading(NavigationController* controller);
    107 
    108   // Invokes |LoadNextTab| to load a tab.
    109   //
    110   // This must be invoked once to start loading.
    111   void StartLoading();
    112 
    113  private:
    114   friend class base::RefCounted<TabLoader>;
    115 
    116   typedef std::set<NavigationController*> TabsLoading;
    117   typedef std::list<NavigationController*> TabsToLoad;
    118   typedef std::set<RenderWidgetHost*> RenderWidgetHostSet;
    119 
    120   explicit TabLoader(base::TimeTicks restore_started);
    121   virtual ~TabLoader();
    122 
    123   // Loads the next tab. If there are no more tabs to load this deletes itself,
    124   // otherwise |force_load_timer_| is restarted.
    125   void LoadNextTab();
    126 
    127   // NotificationObserver method. Removes the specified tab and loads the next
    128   // tab.
    129   virtual void Observe(int type,
    130                        const content::NotificationSource& source,
    131                        const content::NotificationDetails& details) OVERRIDE;
    132 
    133   // net::NetworkChangeNotifier::ConnectionTypeObserver overrides.
    134   virtual void OnConnectionTypeChanged(
    135       net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
    136 
    137   // Removes the listeners from the specified tab and removes the tab from
    138   // the set of tabs to load and list of tabs we're waiting to get a load
    139   // from.
    140   void RemoveTab(NavigationController* tab);
    141 
    142   // Invoked from |force_load_timer_|. Doubles |force_load_delay_| and invokes
    143   // |LoadNextTab| to load the next tab
    144   void ForceLoadTimerFired();
    145 
    146   // Returns the RenderWidgetHost associated with a tab if there is one,
    147   // NULL otherwise.
    148   static RenderWidgetHost* GetRenderWidgetHost(NavigationController* tab);
    149 
    150   // Register for necessary notifications on a tab navigation controller.
    151   void RegisterForNotifications(NavigationController* controller);
    152 
    153   // Called when a tab goes away or a load completes.
    154   void HandleTabClosedOrLoaded(NavigationController* controller);
    155 
    156   // TODO(sky): remove. For debugging 368236.
    157   void CheckNotObserving(NavigationController* controller);
    158 
    159   content::NotificationRegistrar registrar_;
    160 
    161   // Current delay before a new tab is loaded. See class description for
    162   // details.
    163   int64 force_load_delay_;
    164 
    165   // Has Load been invoked?
    166   bool loading_;
    167 
    168   // Have we recorded the times for a tab paint?
    169   bool got_first_paint_;
    170 
    171   // The set of tabs we've initiated loading on. This does NOT include the
    172   // selected tabs.
    173   TabsLoading tabs_loading_;
    174 
    175   // The tabs we need to load.
    176   TabsToLoad tabs_to_load_;
    177 
    178   // The renderers we have started loading into.
    179   RenderWidgetHostSet render_widget_hosts_loading_;
    180 
    181   // The renderers we have loaded and are waiting on to paint.
    182   RenderWidgetHostSet render_widget_hosts_to_paint_;
    183 
    184   // The number of tabs that have been restored.
    185   int tab_count_;
    186 
    187   base::OneShotTimer<TabLoader> force_load_timer_;
    188 
    189   // The time the restore process started.
    190   base::TimeTicks restore_started_;
    191 
    192   // Max number of tabs that were loaded in parallel (for metrics).
    193   size_t max_parallel_tab_loads_;
    194 
    195   // For keeping TabLoader alive while it's loading even if no
    196   // SessionRestoreImpls reference it.
    197   scoped_refptr<TabLoader> this_retainer_;
    198 
    199   DISALLOW_COPY_AND_ASSIGN(TabLoader);
    200 };
    201 
    202 // static
    203 TabLoader* TabLoader::GetTabLoader(base::TimeTicks restore_started) {
    204   if (!shared_tab_loader)
    205     shared_tab_loader = new TabLoader(restore_started);
    206   return shared_tab_loader;
    207 }
    208 
    209 void TabLoader::ScheduleLoad(NavigationController* controller) {
    210   CheckNotObserving(controller);
    211   DCHECK(controller);
    212   DCHECK(find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) ==
    213          tabs_to_load_.end());
    214   tabs_to_load_.push_back(controller);
    215   RegisterForNotifications(controller);
    216 }
    217 
    218 void TabLoader::TabIsLoading(NavigationController* controller) {
    219   CheckNotObserving(controller);
    220   DCHECK(controller);
    221   DCHECK(find(tabs_loading_.begin(), tabs_loading_.end(), controller) ==
    222          tabs_loading_.end());
    223   tabs_loading_.insert(controller);
    224   RenderWidgetHost* render_widget_host = GetRenderWidgetHost(controller);
    225   DCHECK(render_widget_host);
    226   render_widget_hosts_loading_.insert(render_widget_host);
    227   RegisterForNotifications(controller);
    228 }
    229 
    230 void TabLoader::StartLoading() {
    231   // When multiple profiles are using the same TabLoader, another profile might
    232   // already have started loading. In that case, the tabs scheduled for loading
    233   // by this profile are already in the loading queue, and they will get loaded
    234   // eventually.
    235   if (loading_)
    236     return;
    237   registrar_.Add(
    238       this,
    239       content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
    240       content::NotificationService::AllSources());
    241   this_retainer_ = this;
    242 #if defined(OS_CHROMEOS)
    243   if (!net::NetworkChangeNotifier::IsOffline()) {
    244     loading_ = true;
    245     LoadNextTab();
    246   } else {
    247     net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
    248   }
    249 #else
    250   loading_ = true;
    251   LoadNextTab();
    252 #endif
    253 }
    254 
    255 TabLoader::TabLoader(base::TimeTicks restore_started)
    256     : force_load_delay_(kInitialDelayTimerMS),
    257       loading_(false),
    258       got_first_paint_(false),
    259       tab_count_(0),
    260       restore_started_(restore_started),
    261       max_parallel_tab_loads_(0) {
    262 }
    263 
    264 TabLoader::~TabLoader() {
    265   DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
    266           tabs_loading_.empty() && tabs_to_load_.empty());
    267   net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
    268   shared_tab_loader = NULL;
    269 }
    270 
    271 void TabLoader::LoadNextTab() {
    272   if (!tabs_to_load_.empty()) {
    273     NavigationController* tab = tabs_to_load_.front();
    274     DCHECK(tab);
    275     tabs_loading_.insert(tab);
    276     if (tabs_loading_.size() > max_parallel_tab_loads_)
    277       max_parallel_tab_loads_ = tabs_loading_.size();
    278     tabs_to_load_.pop_front();
    279     tab->LoadIfNecessary();
    280     content::WebContents* contents = tab->GetWebContents();
    281     if (contents) {
    282       Browser* browser = chrome::FindBrowserWithWebContents(contents);
    283       if (browser &&
    284           browser->tab_strip_model()->GetActiveWebContents() != contents) {
    285         // By default tabs are marked as visible. As only the active tab is
    286         // visible we need to explicitly tell non-active tabs they are hidden.
    287         // Without this call non-active tabs are not marked as backgrounded.
    288         //
    289         // NOTE: We need to do this here rather than when the tab is added to
    290         // the Browser as at that time not everything has been created, so that
    291         // the call would do nothing.
    292         contents->WasHidden();
    293       }
    294     }
    295   }
    296 
    297   if (!tabs_to_load_.empty()) {
    298     force_load_timer_.Stop();
    299     // Each time we load a tab we also set a timer to force us to start loading
    300     // the next tab if this one doesn't load quickly enough.
    301     force_load_timer_.Start(FROM_HERE,
    302         base::TimeDelta::FromMilliseconds(force_load_delay_),
    303         this, &TabLoader::ForceLoadTimerFired);
    304   }
    305 
    306   // When the session restore is done synchronously, notification is sent from
    307   // SessionRestoreImpl::Restore .
    308   if (tabs_to_load_.empty() && !SessionRestore::IsRestoringSynchronously()) {
    309     content::NotificationService::current()->Notify(
    310         chrome::NOTIFICATION_SESSION_RESTORE_DONE,
    311         content::NotificationService::AllSources(),
    312         content::NotificationService::NoDetails());
    313   }
    314 }
    315 
    316 void TabLoader::Observe(int type,
    317                         const content::NotificationSource& source,
    318                         const content::NotificationDetails& details) {
    319   switch (type) {
    320     case content::NOTIFICATION_LOAD_START: {
    321       // Add this render_widget_host to the set of those we're waiting for
    322       // paints on. We want to only record stats for paints that occur after
    323       // a load has finished.
    324       NavigationController* tab =
    325           content::Source<NavigationController>(source).ptr();
    326       RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
    327       DCHECK(render_widget_host);
    328       render_widget_hosts_loading_.insert(render_widget_host);
    329       break;
    330     }
    331     case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
    332       WebContents* web_contents = content::Source<WebContents>(source).ptr();
    333       if (!got_first_paint_) {
    334         RenderWidgetHost* render_widget_host =
    335             GetRenderWidgetHost(&web_contents->GetController());
    336         render_widget_hosts_loading_.erase(render_widget_host);
    337       }
    338       HandleTabClosedOrLoaded(&web_contents->GetController());
    339       break;
    340     }
    341     case content::NOTIFICATION_LOAD_STOP: {
    342       NavigationController* tab =
    343           content::Source<NavigationController>(source).ptr();
    344       render_widget_hosts_to_paint_.insert(GetRenderWidgetHost(tab));
    345       HandleTabClosedOrLoaded(tab);
    346       break;
    347     }
    348     case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: {
    349       RenderWidgetHost* render_widget_host =
    350           content::Source<RenderWidgetHost>(source).ptr();
    351       if (!got_first_paint_ && render_widget_host->GetView() &&
    352           render_widget_host->GetView()->IsShowing()) {
    353         if (render_widget_hosts_to_paint_.find(render_widget_host) !=
    354             render_widget_hosts_to_paint_.end()) {
    355           // Got a paint for one of our renderers, so record time.
    356           got_first_paint_ = true;
    357           base::TimeDelta time_to_paint =
    358               base::TimeTicks::Now() - restore_started_;
    359           UMA_HISTOGRAM_CUSTOM_TIMES(
    360               "SessionRestore.FirstTabPainted",
    361               time_to_paint,
    362               base::TimeDelta::FromMilliseconds(10),
    363               base::TimeDelta::FromSeconds(100),
    364               100);
    365           // Record a time for the number of tabs, to help track down
    366           // contention.
    367           std::string time_for_count =
    368               base::StringPrintf("SessionRestore.FirstTabPainted_%d",
    369                                  tab_count_);
    370           base::HistogramBase* counter_for_count =
    371               base::Histogram::FactoryTimeGet(
    372                   time_for_count,
    373                   base::TimeDelta::FromMilliseconds(10),
    374                   base::TimeDelta::FromSeconds(100),
    375                   100,
    376                   base::Histogram::kUmaTargetedHistogramFlag);
    377           counter_for_count->AddTime(time_to_paint);
    378         } else if (render_widget_hosts_loading_.find(render_widget_host) ==
    379             render_widget_hosts_loading_.end()) {
    380           // If this is a host for a tab we're not loading some other tab
    381           // has rendered and there's no point tracking the time. This could
    382           // happen because the user opened a different tab or restored tabs
    383           // to an already existing browser and an existing tab painted.
    384           got_first_paint_ = true;
    385         }
    386       }
    387       break;
    388     }
    389     default:
    390       NOTREACHED() << "Unknown notification received:" << type;
    391   }
    392   // Delete ourselves when we're not waiting for any more notifications. If this
    393   // was not the last reference, a SessionRestoreImpl holding a reference will
    394   // eventually call StartLoading (which assigns this_retainer_), or drop the
    395   // reference without initiating a load.
    396   if ((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
    397       tabs_loading_.empty() && tabs_to_load_.empty())
    398     this_retainer_ = NULL;
    399 }
    400 
    401 void TabLoader::OnConnectionTypeChanged(
    402     net::NetworkChangeNotifier::ConnectionType type) {
    403   if (type != net::NetworkChangeNotifier::CONNECTION_NONE) {
    404     if (!loading_) {
    405       loading_ = true;
    406       LoadNextTab();
    407     }
    408   } else {
    409     loading_ = false;
    410   }
    411 }
    412 
    413 void TabLoader::RemoveTab(NavigationController* tab) {
    414   registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
    415                     content::Source<WebContents>(tab->GetWebContents()));
    416   registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP,
    417                     content::Source<NavigationController>(tab));
    418   registrar_.Remove(this, content::NOTIFICATION_LOAD_START,
    419                     content::Source<NavigationController>(tab));
    420 
    421   TabsLoading::iterator i = tabs_loading_.find(tab);
    422   if (i != tabs_loading_.end())
    423     tabs_loading_.erase(i);
    424 
    425   TabsToLoad::iterator j =
    426       find(tabs_to_load_.begin(), tabs_to_load_.end(), tab);
    427   if (j != tabs_to_load_.end())
    428     tabs_to_load_.erase(j);
    429 }
    430 
    431 void TabLoader::ForceLoadTimerFired() {
    432   force_load_delay_ *= 2;
    433   LoadNextTab();
    434 }
    435 
    436 RenderWidgetHost* TabLoader::GetRenderWidgetHost(NavigationController* tab) {
    437   WebContents* web_contents = tab->GetWebContents();
    438   if (web_contents) {
    439     content::RenderWidgetHostView* render_widget_host_view =
    440         web_contents->GetRenderWidgetHostView();
    441     if (render_widget_host_view)
    442       return render_widget_host_view->GetRenderWidgetHost();
    443   }
    444   return NULL;
    445 }
    446 
    447 void TabLoader::RegisterForNotifications(NavigationController* controller) {
    448   registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
    449                  content::Source<WebContents>(controller->GetWebContents()));
    450   registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
    451                  content::Source<NavigationController>(controller));
    452   registrar_.Add(this, content::NOTIFICATION_LOAD_START,
    453                  content::Source<NavigationController>(controller));
    454   ++tab_count_;
    455 }
    456 
    457 void TabLoader::HandleTabClosedOrLoaded(NavigationController* tab) {
    458   RemoveTab(tab);
    459   if (loading_)
    460     LoadNextTab();
    461   if (tabs_loading_.empty() && tabs_to_load_.empty()) {
    462     base::TimeDelta time_to_load =
    463         base::TimeTicks::Now() - restore_started_;
    464     performance_monitor::StartupTimer::SetElapsedSessionRestoreTime(
    465         time_to_load);
    466     UMA_HISTOGRAM_CUSTOM_TIMES(
    467         "SessionRestore.AllTabsLoaded",
    468         time_to_load,
    469         base::TimeDelta::FromMilliseconds(10),
    470         base::TimeDelta::FromSeconds(100),
    471         100);
    472     // Record a time for the number of tabs, to help track down contention.
    473     std::string time_for_count =
    474         base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_);
    475     base::HistogramBase* counter_for_count =
    476         base::Histogram::FactoryTimeGet(
    477             time_for_count,
    478             base::TimeDelta::FromMilliseconds(10),
    479             base::TimeDelta::FromSeconds(100),
    480             100,
    481             base::Histogram::kUmaTargetedHistogramFlag);
    482     counter_for_count->AddTime(time_to_load);
    483 
    484     UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads",
    485                              max_parallel_tab_loads_);
    486   }
    487 }
    488 
    489 void TabLoader::CheckNotObserving(NavigationController* controller) {
    490   const bool in_tabs_to_load =
    491       find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) !=
    492           tabs_to_load_.end();
    493   const bool in_tabs_loading =
    494       find(tabs_loading_.begin(), tabs_loading_.end(), controller) !=
    495           tabs_loading_.end();
    496   const bool observing =
    497       registrar_.IsRegistered(
    498           this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
    499           content::Source<WebContents>(controller->GetWebContents())) ||
    500       registrar_.IsRegistered(
    501           this, content::NOTIFICATION_LOAD_STOP,
    502           content::Source<NavigationController>(controller)) ||
    503       registrar_.IsRegistered(
    504           this, content::NOTIFICATION_LOAD_START,
    505           content::Source<NavigationController>(controller));
    506   base::debug::Alias(&in_tabs_to_load);
    507   base::debug::Alias(&in_tabs_loading);
    508   base::debug::Alias(&observing);
    509   CHECK(!in_tabs_to_load && !in_tabs_loading && !observing);
    510 }
    511 
    512 // SessionRestoreImpl ---------------------------------------------------------
    513 
    514 // SessionRestoreImpl is responsible for fetching the set of tabs to create
    515 // from SessionService. SessionRestoreImpl deletes itself when done.
    516 
    517 class SessionRestoreImpl : public content::NotificationObserver {
    518  public:
    519   SessionRestoreImpl(Profile* profile,
    520                      Browser* browser,
    521                      chrome::HostDesktopType host_desktop_type,
    522                      bool synchronous,
    523                      bool clobber_existing_tab,
    524                      bool always_create_tabbed_browser,
    525                      const std::vector<GURL>& urls_to_open)
    526       : profile_(profile),
    527         browser_(browser),
    528         host_desktop_type_(host_desktop_type),
    529         synchronous_(synchronous),
    530         clobber_existing_tab_(clobber_existing_tab),
    531         always_create_tabbed_browser_(always_create_tabbed_browser),
    532         urls_to_open_(urls_to_open),
    533         active_window_id_(0),
    534         restore_started_(base::TimeTicks::Now()),
    535         browser_shown_(false) {
    536     // For sanity's sake, if |browser| is non-null: force |host_desktop_type| to
    537     // be the same as |browser|'s desktop type.
    538     DCHECK(!browser || browser->host_desktop_type() == host_desktop_type);
    539 
    540     if (active_session_restorers == NULL)
    541       active_session_restorers = new std::set<SessionRestoreImpl*>();
    542 
    543     // Only one SessionRestoreImpl should be operating on the profile at the
    544     // same time.
    545     std::set<SessionRestoreImpl*>::const_iterator it;
    546     for (it = active_session_restorers->begin();
    547          it != active_session_restorers->end(); ++it) {
    548       if ((*it)->profile_ == profile)
    549         break;
    550     }
    551     DCHECK(it == active_session_restorers->end());
    552 
    553     active_session_restorers->insert(this);
    554 
    555     // When asynchronous its possible for there to be no windows. To make sure
    556     // Chrome doesn't prematurely exit AddRef the process. We'll release in the
    557     // destructor when restore is done.
    558     g_browser_process->AddRefModule();
    559   }
    560 
    561   bool synchronous() const { return synchronous_; }
    562 
    563   Browser* Restore() {
    564     SessionService* session_service =
    565         SessionServiceFactory::GetForProfile(profile_);
    566     DCHECK(session_service);
    567     session_service->GetLastSession(
    568         base::Bind(&SessionRestoreImpl::OnGotSession, base::Unretained(this)),
    569         &cancelable_task_tracker_);
    570 
    571     if (synchronous_) {
    572       {
    573         base::MessageLoop::ScopedNestableTaskAllower allow(
    574             base::MessageLoop::current());
    575         base::RunLoop loop;
    576         quit_closure_for_sync_restore_ = loop.QuitClosure();
    577         loop.Run();
    578         quit_closure_for_sync_restore_ = base::Closure();
    579       }
    580       Browser* browser = ProcessSessionWindows(&windows_, active_window_id_);
    581       delete this;
    582       content::NotificationService::current()->Notify(
    583           chrome::NOTIFICATION_SESSION_RESTORE_DONE,
    584           content::NotificationService::AllSources(),
    585           content::NotificationService::NoDetails());
    586       return browser;
    587     }
    588 
    589     if (browser_) {
    590       registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
    591                      content::Source<Browser>(browser_));
    592     }
    593 
    594     return browser_;
    595   }
    596 
    597   // Restore window(s) from a foreign session. Returns newly created Browsers.
    598   std::vector<Browser*> RestoreForeignSession(
    599       std::vector<const SessionWindow*>::const_iterator begin,
    600       std::vector<const SessionWindow*>::const_iterator end) {
    601     StartTabCreation();
    602     std::vector<Browser*> browsers;
    603     // Create a browser instance to put the restored tabs in.
    604     for (std::vector<const SessionWindow*>::const_iterator i = begin;
    605          i != end; ++i) {
    606       Browser* browser = CreateRestoredBrowser(
    607           static_cast<Browser::Type>((*i)->type),
    608           (*i)->bounds,
    609           (*i)->show_state,
    610           (*i)->app_name);
    611       browsers.push_back(browser);
    612 
    613       // Restore and show the browser.
    614       const int initial_tab_count = 0;
    615       int selected_tab_index = std::max(
    616           0,
    617           std::min((*i)->selected_tab_index,
    618                    static_cast<int>((*i)->tabs.size()) - 1));
    619       RestoreTabsToBrowser(*(*i), browser, initial_tab_count,
    620                            selected_tab_index);
    621       NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
    622     }
    623 
    624     // Always create in a new window
    625     FinishedTabCreation(true, true);
    626     return browsers;
    627   }
    628 
    629   // Restore a single tab from a foreign session.
    630   // Opens in the tab in the last active browser, unless disposition is
    631   // NEW_WINDOW, in which case the tab will be opened in a new browser. Returns
    632   // the WebContents of the restored tab.
    633   WebContents* RestoreForeignTab(const SessionTab& tab,
    634                                  WindowOpenDisposition disposition) {
    635     DCHECK(!tab.navigations.empty());
    636     int selected_index = tab.current_navigation_index;
    637     selected_index = std::max(
    638         0,
    639         std::min(selected_index,
    640                  static_cast<int>(tab.navigations.size() - 1)));
    641 
    642     bool use_new_window = disposition == NEW_WINDOW;
    643 
    644     Browser* browser = use_new_window ?
    645         new Browser(Browser::CreateParams(profile_, host_desktop_type_)) :
    646         browser_;
    647 
    648     RecordAppLaunchForTab(browser, tab, selected_index);
    649 
    650     WebContents* web_contents;
    651     if (disposition == CURRENT_TAB) {
    652       DCHECK(!use_new_window);
    653       web_contents = chrome::ReplaceRestoredTab(browser,
    654                                                 tab.navigations,
    655                                                 selected_index,
    656                                                 true,
    657                                                 tab.extension_app_id,
    658                                                 NULL,
    659                                                 tab.user_agent_override);
    660     } else {
    661       int tab_index =
    662           use_new_window ? 0 : browser->tab_strip_model()->active_index() + 1;
    663       web_contents = chrome::AddRestoredTab(
    664           browser,
    665           tab.navigations,
    666           tab_index,
    667           selected_index,
    668           tab.extension_app_id,
    669           disposition == NEW_FOREGROUND_TAB,  // selected
    670           tab.pinned,
    671           true,
    672           NULL,
    673           tab.user_agent_override);
    674       // Start loading the tab immediately.
    675       web_contents->GetController().LoadIfNecessary();
    676     }
    677 
    678     if (use_new_window) {
    679       browser->tab_strip_model()->ActivateTabAt(0, true);
    680       browser->window()->Show();
    681     }
    682     NotifySessionServiceOfRestoredTabs(browser,
    683                                        browser->tab_strip_model()->count());
    684 
    685     // Since FinishedTabCreation() is not called here, |this| will leak if we
    686     // are not in sychronous mode.
    687     DCHECK(synchronous_);
    688     return web_contents;
    689   }
    690 
    691   virtual ~SessionRestoreImpl() {
    692     STLDeleteElements(&windows_);
    693 
    694     active_session_restorers->erase(this);
    695     if (active_session_restorers->empty()) {
    696       delete active_session_restorers;
    697       active_session_restorers = NULL;
    698     }
    699 
    700     g_browser_process->ReleaseModule();
    701   }
    702 
    703   virtual void Observe(int type,
    704                        const content::NotificationSource& source,
    705                        const content::NotificationDetails& details) OVERRIDE {
    706     switch (type) {
    707       case chrome::NOTIFICATION_BROWSER_CLOSED:
    708         delete this;
    709         return;
    710 
    711       default:
    712         NOTREACHED();
    713         break;
    714     }
    715   }
    716 
    717   Profile* profile() { return profile_; }
    718 
    719  private:
    720   // Invoked when beginning to create new tabs. Resets the tab_loader_.
    721   void StartTabCreation() {
    722     tab_loader_ = TabLoader::GetTabLoader(restore_started_);
    723   }
    724 
    725   // Invoked when done with creating all the tabs/browsers.
    726   //
    727   // |created_tabbed_browser| indicates whether a tabbed browser was created,
    728   // or we used an existing tabbed browser.
    729   //
    730   // If successful, this begins loading tabs and deletes itself when all tabs
    731   // have been loaded.
    732   //
    733   // Returns the Browser that was created, if any.
    734   Browser* FinishedTabCreation(bool succeeded, bool created_tabbed_browser) {
    735     Browser* browser = NULL;
    736     if (!created_tabbed_browser && always_create_tabbed_browser_) {
    737       browser = new Browser(Browser::CreateParams(profile_,
    738                                                   host_desktop_type_));
    739       if (urls_to_open_.empty()) {
    740         // No tab browsers were created and no URLs were supplied on the command
    741         // line. Open the new tab page.
    742         urls_to_open_.push_back(GURL(chrome::kChromeUINewTabURL));
    743       }
    744       AppendURLsToBrowser(browser, urls_to_open_);
    745       browser->window()->Show();
    746     }
    747 
    748     if (succeeded) {
    749       DCHECK(tab_loader_.get());
    750       // TabLoader deletes itself when done loading.
    751       tab_loader_->StartLoading();
    752       tab_loader_ = NULL;
    753     }
    754 
    755     if (!synchronous_) {
    756       // If we're not synchronous we need to delete ourself.
    757       // NOTE: we must use DeleteLater here as most likely we're in a callback
    758       // from the history service which doesn't deal well with deleting the
    759       // object it is notifying.
    760       base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
    761 
    762       // The delete may take a while and at this point we no longer care about
    763       // if the browser is deleted. Don't listen to anything. This avoid a
    764       // possible double delete too (if browser is closed before DeleteSoon() is
    765       // processed).
    766       registrar_.RemoveAll();
    767     }
    768 
    769 #if defined(OS_CHROMEOS)
    770     chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
    771         "SessionRestore-End", false);
    772 #endif
    773     return browser;
    774   }
    775 
    776   void OnGotSession(ScopedVector<SessionWindow> windows,
    777                     SessionID::id_type active_window_id) {
    778     base::TimeDelta time_to_got_sessions =
    779         base::TimeTicks::Now() - restore_started_;
    780     UMA_HISTOGRAM_CUSTOM_TIMES(
    781         "SessionRestore.TimeToGotSessions",
    782         time_to_got_sessions,
    783         base::TimeDelta::FromMilliseconds(10),
    784         base::TimeDelta::FromSeconds(1000),
    785         100);
    786 #if defined(OS_CHROMEOS)
    787     chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
    788         "SessionRestore-GotSession", false);
    789 #endif
    790     if (synchronous_) {
    791       // See comment above windows_ as to why we don't process immediately.
    792       windows_.swap(windows.get());
    793       active_window_id_ = active_window_id;
    794       CHECK(!quit_closure_for_sync_restore_.is_null());
    795       quit_closure_for_sync_restore_.Run();
    796       return;
    797     }
    798 
    799     ProcessSessionWindows(&windows.get(), active_window_id);
    800   }
    801 
    802   Browser* ProcessSessionWindows(std::vector<SessionWindow*>* windows,
    803                                  SessionID::id_type active_window_id) {
    804     VLOG(1) << "ProcessSessionWindows " << windows->size();
    805     base::TimeDelta time_to_process_sessions =
    806         base::TimeTicks::Now() - restore_started_;
    807     UMA_HISTOGRAM_CUSTOM_TIMES(
    808         "SessionRestore.TimeToProcessSessions",
    809         time_to_process_sessions,
    810         base::TimeDelta::FromMilliseconds(10),
    811         base::TimeDelta::FromSeconds(1000),
    812         100);
    813 
    814     if (windows->empty()) {
    815       // Restore was unsuccessful. The DOM storage system can also delete its
    816       // data, since no session restore will happen at a later point in time.
    817       content::BrowserContext::GetDefaultStoragePartition(profile_)->
    818           GetDOMStorageContext()->StartScavengingUnusedSessionStorage();
    819       return FinishedTabCreation(false, false);
    820     }
    821 
    822 #if defined(OS_CHROMEOS)
    823     chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
    824         "SessionRestore-CreatingTabs-Start", false);
    825 #endif
    826     StartTabCreation();
    827 
    828     // After the for loop this contains the last TABBED_BROWSER. Is null if no
    829     // tabbed browsers exist.
    830     Browser* last_browser = NULL;
    831     bool has_tabbed_browser = false;
    832 
    833     // After the for loop, this contains the browser to activate, if one of the
    834     // windows has the same id as specified in active_window_id.
    835     Browser* browser_to_activate = NULL;
    836 #if defined(OS_WIN)
    837     int selected_tab_to_activate = -1;
    838 #endif
    839 
    840     // Determine if there is a visible window.
    841     bool has_visible_browser = false;
    842     for (std::vector<SessionWindow*>::iterator i = windows->begin();
    843          i != windows->end(); ++i) {
    844       if ((*i)->show_state != ui::SHOW_STATE_MINIMIZED)
    845         has_visible_browser = true;
    846     }
    847 
    848     for (std::vector<SessionWindow*>::iterator i = windows->begin();
    849          i != windows->end(); ++i) {
    850       Browser* browser = NULL;
    851       if (!has_tabbed_browser && (*i)->type == Browser::TYPE_TABBED)
    852         has_tabbed_browser = true;
    853       if (i == windows->begin() && (*i)->type == Browser::TYPE_TABBED &&
    854           browser_ && browser_->is_type_tabbed() &&
    855           !browser_->profile()->IsOffTheRecord()) {
    856         // The first set of tabs is added to the existing browser.
    857         browser = browser_;
    858       } else {
    859 #if defined(OS_CHROMEOS)
    860         chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
    861             "SessionRestore-CreateRestoredBrowser-Start", false);
    862 #endif
    863         // Show the first window if none are visible.
    864         ui::WindowShowState show_state = (*i)->show_state;
    865         if (!has_visible_browser) {
    866           show_state = ui::SHOW_STATE_NORMAL;
    867           has_visible_browser = true;
    868         }
    869         browser = CreateRestoredBrowser(
    870             static_cast<Browser::Type>((*i)->type),
    871             (*i)->bounds,
    872             show_state,
    873             (*i)->app_name);
    874 #if defined(OS_CHROMEOS)
    875         chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
    876             "SessionRestore-CreateRestoredBrowser-End", false);
    877 #endif
    878       }
    879       if ((*i)->type == Browser::TYPE_TABBED)
    880         last_browser = browser;
    881       WebContents* active_tab =
    882           browser->tab_strip_model()->GetActiveWebContents();
    883       int initial_tab_count = browser->tab_strip_model()->count();
    884       bool close_active_tab = clobber_existing_tab_ &&
    885                               i == windows->begin() &&
    886                               (*i)->type == Browser::TYPE_TABBED &&
    887                               active_tab && browser == browser_ &&
    888                               (*i)->tabs.size() > 0;
    889       if (close_active_tab)
    890         --initial_tab_count;
    891       int selected_tab_index =
    892           initial_tab_count > 0 ? browser->tab_strip_model()->active_index()
    893                                 : std::max(0,
    894                                     std::min((*i)->selected_tab_index,
    895                                     static_cast<int>((*i)->tabs.size()) - 1));
    896       if ((*i)->window_id.id() == active_window_id) {
    897         browser_to_activate = browser;
    898 #if defined(OS_WIN)
    899         selected_tab_to_activate = selected_tab_index;
    900 #endif
    901       }
    902       RestoreTabsToBrowser(*(*i), browser, initial_tab_count,
    903                            selected_tab_index);
    904       NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
    905       // This needs to be done after restore because closing the last tab will
    906       // close the whole window.
    907       if (close_active_tab)
    908         chrome::CloseWebContents(browser, active_tab, true);
    909 #if defined(OS_WIN)
    910         selected_tab_to_activate = -1;
    911 #endif
    912     }
    913 
    914     if (browser_to_activate && browser_to_activate->is_type_tabbed())
    915       last_browser = browser_to_activate;
    916 
    917     if (last_browser && !urls_to_open_.empty())
    918       AppendURLsToBrowser(last_browser, urls_to_open_);
    919 #if defined(OS_CHROMEOS)
    920     chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
    921         "SessionRestore-CreatingTabs-End", false);
    922 #endif
    923     if (browser_to_activate)
    924       browser_to_activate->window()->Activate();
    925 
    926     // If last_browser is NULL and urls_to_open_ is non-empty,
    927     // FinishedTabCreation will create a new TabbedBrowser and add the urls to
    928     // it.
    929     Browser* finished_browser = FinishedTabCreation(true, has_tabbed_browser);
    930     if (finished_browser)
    931       last_browser = finished_browser;
    932 
    933     // sessionStorages needed for the session restore have now been recreated
    934     // by RestoreTab. Now it's safe for the DOM storage system to start
    935     // deleting leftover data.
    936     content::BrowserContext::GetDefaultStoragePartition(profile_)->
    937         GetDOMStorageContext()->StartScavengingUnusedSessionStorage();
    938     return last_browser;
    939   }
    940 
    941   // Record an app launch event (if appropriate) for a tab which is about to
    942   // be restored. Callers should ensure that selected_index is within the
    943   // bounds of tab.navigations before calling.
    944   void RecordAppLaunchForTab(Browser* browser,
    945                              const SessionTab& tab,
    946                              int selected_index) {
    947     DCHECK(selected_index >= 0 &&
    948            selected_index < static_cast<int>(tab.navigations.size()));
    949     GURL url = tab.navigations[selected_index].virtual_url();
    950     const extensions::Extension* extension =
    951         extensions::ExtensionRegistry::Get(profile())
    952             ->enabled_extensions().GetAppByURL(url);
    953     if (extension) {
    954       CoreAppLauncherHandler::RecordAppLaunchType(
    955           extension_misc::APP_LAUNCH_SESSION_RESTORE,
    956           extension->GetType());
    957     }
    958   }
    959 
    960   // Adds the tabs from |window| to |browser|. Normal tabs go after the existing
    961   // tabs but pinned tabs will be pushed in front.
    962   // If there are no existing tabs, the tab at |selected_tab_index| will be
    963   // selected. Otherwise, the tab selection will remain untouched.
    964   void RestoreTabsToBrowser(const SessionWindow& window,
    965                            Browser* browser,
    966                            int initial_tab_count,
    967                            int selected_tab_index) {
    968     VLOG(1) << "RestoreTabsToBrowser " << window.tabs.size();
    969     DCHECK(!window.tabs.empty());
    970     if (initial_tab_count == 0) {
    971       for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
    972         const SessionTab& tab = *(window.tabs[i]);
    973 
    974         // Loads are scheduled for each restored tab unless the tab is going to
    975         // be selected as ShowBrowser() will load the selected tab.
    976         bool is_not_selected_tab = (i != selected_tab_index);
    977         WebContents* restored_tab =
    978             RestoreTab(tab, i, browser, is_not_selected_tab);
    979 
    980         // RestoreTab can return NULL if |tab| doesn't have valid data.
    981         if (!restored_tab)
    982           continue;
    983 
    984         // If this isn't the selected tab, there's nothing else to do.
    985         if (is_not_selected_tab)
    986           continue;
    987 
    988         ShowBrowser(
    989             browser,
    990             browser->tab_strip_model()->GetIndexOfWebContents(restored_tab));
    991         // TODO(sky): remove. For debugging 368236.
    992         CHECK_EQ(browser->tab_strip_model()->GetActiveWebContents(),
    993                  restored_tab);
    994         tab_loader_->TabIsLoading(&browser->tab_strip_model()
    995                                        ->GetActiveWebContents()
    996                                        ->GetController());
    997       }
    998     } else {
    999       // If the browser already has tabs, we want to restore the new ones after
   1000       // the existing ones. E.g. this happens in Win8 Metro where we merge
   1001       // windows or when launching a hosted app from the app launcher.
   1002       int tab_index_offset = initial_tab_count;
   1003       for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
   1004         const SessionTab& tab = *(window.tabs[i]);
   1005         // Always schedule loads as we will not be calling ShowBrowser().
   1006         RestoreTab(tab, tab_index_offset + i, browser, true);
   1007       }
   1008     }
   1009   }
   1010 
   1011   // |tab_index| is ignored for pinned tabs which will always be pushed behind
   1012   // the last existing pinned tab.
   1013   // |schedule_load| will let |tab_loader_| know that it should schedule this
   1014   // tab for loading.
   1015   WebContents* RestoreTab(const SessionTab& tab,
   1016                           const int tab_index,
   1017                           Browser* browser,
   1018                           bool schedule_load) {
   1019     // It's possible (particularly for foreign sessions) to receive a tab
   1020     // without valid navigations. In that case, just skip it.
   1021     // See crbug.com/154129.
   1022     if (tab.navigations.empty())
   1023       return NULL;
   1024     int selected_index = tab.current_navigation_index;
   1025     selected_index = std::max(
   1026         0,
   1027         std::min(selected_index,
   1028                  static_cast<int>(tab.navigations.size() - 1)));
   1029 
   1030     RecordAppLaunchForTab(browser, tab, selected_index);
   1031 
   1032     // Associate sessionStorage (if any) to the restored tab.
   1033     scoped_refptr<content::SessionStorageNamespace> session_storage_namespace;
   1034     if (!tab.session_storage_persistent_id.empty()) {
   1035       session_storage_namespace =
   1036           content::BrowserContext::GetDefaultStoragePartition(profile_)->
   1037               GetDOMStorageContext()->RecreateSessionStorage(
   1038                   tab.session_storage_persistent_id);
   1039     }
   1040 
   1041     WebContents* web_contents =
   1042         chrome::AddRestoredTab(browser,
   1043                                tab.navigations,
   1044                                tab_index,
   1045                                selected_index,
   1046                                tab.extension_app_id,
   1047                                false,  // select
   1048                                tab.pinned,
   1049                                true,
   1050                                session_storage_namespace.get(),
   1051                                tab.user_agent_override);
   1052     // Regression check: check that the tab didn't start loading right away. The
   1053     // focused tab will be loaded by Browser, and TabLoader will load the rest.
   1054     DCHECK(web_contents->GetController().NeedsReload());
   1055 
   1056     // Set up the file access rights for the selected navigation entry.
   1057     const int id = web_contents->GetRenderProcessHost()->GetID();
   1058     const content::PageState& page_state =
   1059         tab.navigations.at(selected_index).page_state();
   1060     const std::vector<base::FilePath>& file_paths =
   1061         page_state.GetReferencedFiles();
   1062     for (std::vector<base::FilePath>::const_iterator file = file_paths.begin();
   1063          file != file_paths.end(); ++file) {
   1064       content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(id,
   1065                                                                         *file);
   1066     }
   1067 
   1068     if (schedule_load)
   1069       tab_loader_->ScheduleLoad(&web_contents->GetController());
   1070     return web_contents;
   1071   }
   1072 
   1073   Browser* CreateRestoredBrowser(Browser::Type type,
   1074                                  gfx::Rect bounds,
   1075                                  ui::WindowShowState show_state,
   1076                                  const std::string& app_name) {
   1077     Browser::CreateParams params(type, profile_, host_desktop_type_);
   1078     if (!app_name.empty()) {
   1079       const bool trusted_source = true;  // We only store trusted app windows.
   1080       params = Browser::CreateParams::CreateForApp(app_name,
   1081                                                    trusted_source,
   1082                                                    bounds,
   1083                                                    profile_,
   1084                                                    host_desktop_type_);
   1085     } else {
   1086       params.initial_bounds = bounds;
   1087     }
   1088     params.initial_show_state = show_state;
   1089     params.is_session_restore = true;
   1090     return new Browser(params);
   1091   }
   1092 
   1093   void ShowBrowser(Browser* browser, int selected_tab_index) {
   1094     DCHECK(browser);
   1095     DCHECK(browser->tab_strip_model()->count());
   1096     browser->tab_strip_model()->ActivateTabAt(selected_tab_index, true);
   1097 
   1098     if (browser_ == browser)
   1099       return;
   1100 
   1101     browser->window()->Show();
   1102     browser->set_is_session_restore(false);
   1103 
   1104     // TODO(jcampan): http://crbug.com/8123 we should not need to set the
   1105     //                initial focus explicitly.
   1106     browser->tab_strip_model()->GetActiveWebContents()->SetInitialFocus();
   1107 
   1108     if (!browser_shown_) {
   1109       browser_shown_ = true;
   1110       base::TimeDelta time_to_first_show =
   1111           base::TimeTicks::Now() - restore_started_;
   1112       UMA_HISTOGRAM_CUSTOM_TIMES(
   1113           "SessionRestore.TimeToFirstShow",
   1114           time_to_first_show,
   1115           base::TimeDelta::FromMilliseconds(10),
   1116           base::TimeDelta::FromSeconds(1000),
   1117           100);
   1118     }
   1119   }
   1120 
   1121   // Appends the urls in |urls| to |browser|.
   1122   void AppendURLsToBrowser(Browser* browser,
   1123                            const std::vector<GURL>& urls) {
   1124     for (size_t i = 0; i < urls.size(); ++i) {
   1125       int add_types = TabStripModel::ADD_FORCE_INDEX;
   1126       if (i == 0)
   1127         add_types |= TabStripModel::ADD_ACTIVE;
   1128       chrome::NavigateParams params(browser, urls[i],
   1129                                     content::PAGE_TRANSITION_AUTO_TOPLEVEL);
   1130       params.disposition = i == 0 ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
   1131       params.tabstrip_add_types = add_types;
   1132       chrome::Navigate(&params);
   1133     }
   1134   }
   1135 
   1136   // Invokes TabRestored on the SessionService for all tabs in browser after
   1137   // initial_count.
   1138   void NotifySessionServiceOfRestoredTabs(Browser* browser, int initial_count) {
   1139     SessionService* session_service =
   1140         SessionServiceFactory::GetForProfile(profile_);
   1141     if (!session_service)
   1142       return;
   1143     TabStripModel* tab_strip = browser->tab_strip_model();
   1144     for (int i = initial_count; i < tab_strip->count(); ++i)
   1145       session_service->TabRestored(tab_strip->GetWebContentsAt(i),
   1146                                    tab_strip->IsTabPinned(i));
   1147   }
   1148 
   1149   // The profile to create the sessions for.
   1150   Profile* profile_;
   1151 
   1152   // The first browser to restore to, may be null.
   1153   Browser* browser_;
   1154 
   1155   // The desktop on which all new browsers should be created (browser_, if it is
   1156   // not NULL, must be of this desktop type as well).
   1157   chrome::HostDesktopType host_desktop_type_;
   1158 
   1159   // Whether or not restore is synchronous.
   1160   const bool synchronous_;
   1161 
   1162   // The quit-closure to terminate the nested message-loop started for
   1163   // synchronous session-restore.
   1164   base::Closure quit_closure_for_sync_restore_;
   1165 
   1166   // See description of CLOBBER_CURRENT_TAB.
   1167   const bool clobber_existing_tab_;
   1168 
   1169   // If true and there is an error or there are no windows to restore, we
   1170   // create a tabbed browser anyway. This is used on startup to make sure at
   1171   // at least one window is created.
   1172   const bool always_create_tabbed_browser_;
   1173 
   1174   // Set of URLs to open in addition to those restored from the session.
   1175   std::vector<GURL> urls_to_open_;
   1176 
   1177   // Used to get the session.
   1178   base::CancelableTaskTracker cancelable_task_tracker_;
   1179 
   1180   // Responsible for loading the tabs.
   1181   scoped_refptr<TabLoader> tab_loader_;
   1182 
   1183   // When synchronous we run a nested message loop. To avoid creating windows
   1184   // from the nested message loop (which can make exiting the nested message
   1185   // loop take a while) we cache the SessionWindows here and create the actual
   1186   // windows when the nested message loop exits.
   1187   std::vector<SessionWindow*> windows_;
   1188   SessionID::id_type active_window_id_;
   1189 
   1190   content::NotificationRegistrar registrar_;
   1191 
   1192   // The time we started the restore.
   1193   base::TimeTicks restore_started_;
   1194 
   1195   // Set to true after the first browser is shown.
   1196   bool browser_shown_;
   1197 
   1198   DISALLOW_COPY_AND_ASSIGN(SessionRestoreImpl);
   1199 };
   1200 
   1201 }  // namespace
   1202 
   1203 // SessionRestore -------------------------------------------------------------
   1204 
   1205 // static
   1206 Browser* SessionRestore::RestoreSession(
   1207     Profile* profile,
   1208     Browser* browser,
   1209     chrome::HostDesktopType host_desktop_type,
   1210     uint32 behavior,
   1211     const std::vector<GURL>& urls_to_open) {
   1212 #if defined(OS_CHROMEOS)
   1213   chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
   1214       "SessionRestore-Start", false);
   1215 #endif
   1216   DCHECK(profile);
   1217   // Always restore from the original profile (incognito profiles have no
   1218   // session service).
   1219   profile = profile->GetOriginalProfile();
   1220   if (!SessionServiceFactory::GetForProfile(profile)) {
   1221     NOTREACHED();
   1222     return NULL;
   1223   }
   1224   profile->set_restored_last_session(true);
   1225   // SessionRestoreImpl takes care of deleting itself when done.
   1226   SessionRestoreImpl* restorer = new SessionRestoreImpl(
   1227       profile, browser, host_desktop_type, (behavior & SYNCHRONOUS) != 0,
   1228       (behavior & CLOBBER_CURRENT_TAB) != 0,
   1229       (behavior & ALWAYS_CREATE_TABBED_BROWSER) != 0,
   1230       urls_to_open);
   1231   return restorer->Restore();
   1232 }
   1233 
   1234 // static
   1235 void SessionRestore::RestoreSessionAfterCrash(Browser* browser) {
   1236    uint32 behavior = 0;
   1237   if (browser->tab_strip_model()->count() == 1) {
   1238     const content::WebContents* active_tab =
   1239         browser->tab_strip_model()->GetWebContentsAt(0);
   1240     if (active_tab->GetURL() == GURL(chrome::kChromeUINewTabURL) ||
   1241         chrome::IsInstantNTP(active_tab)) {
   1242       // There is only one tab and its the new tab page, make session restore
   1243       // clobber it.
   1244       behavior = SessionRestore::CLOBBER_CURRENT_TAB;
   1245     }
   1246   }
   1247   SessionRestore::RestoreSession(browser->profile(), browser,
   1248                                  browser->host_desktop_type(), behavior,
   1249                                  std::vector<GURL>());
   1250 }
   1251 
   1252 // static
   1253 std::vector<Browser*> SessionRestore::RestoreForeignSessionWindows(
   1254     Profile* profile,
   1255     chrome::HostDesktopType host_desktop_type,
   1256     std::vector<const SessionWindow*>::const_iterator begin,
   1257     std::vector<const SessionWindow*>::const_iterator end) {
   1258   std::vector<GURL> gurls;
   1259   SessionRestoreImpl restorer(profile,
   1260       static_cast<Browser*>(NULL), host_desktop_type, true, false, true, gurls);
   1261   return restorer.RestoreForeignSession(begin, end);
   1262 }
   1263 
   1264 // static
   1265 WebContents* SessionRestore::RestoreForeignSessionTab(
   1266     content::WebContents* source_web_contents,
   1267     const SessionTab& tab,
   1268     WindowOpenDisposition disposition) {
   1269   Browser* browser = chrome::FindBrowserWithWebContents(source_web_contents);
   1270   Profile* profile = browser->profile();
   1271   std::vector<GURL> gurls;
   1272   SessionRestoreImpl restorer(profile, browser, browser->host_desktop_type(),
   1273                               true, false, false, gurls);
   1274   return restorer.RestoreForeignTab(tab, disposition);
   1275 }
   1276 
   1277 // static
   1278 bool SessionRestore::IsRestoring(const Profile* profile) {
   1279   if (active_session_restorers == NULL)
   1280     return false;
   1281   for (std::set<SessionRestoreImpl*>::const_iterator it =
   1282            active_session_restorers->begin();
   1283        it != active_session_restorers->end(); ++it) {
   1284     if ((*it)->profile() == profile)
   1285       return true;
   1286   }
   1287   return false;
   1288 }
   1289 
   1290 // static
   1291 bool SessionRestore::IsRestoringSynchronously() {
   1292   if (!active_session_restorers)
   1293     return false;
   1294   for (std::set<SessionRestoreImpl*>::const_iterator it =
   1295            active_session_restorers->begin();
   1296        it != active_session_restorers->end(); ++it) {
   1297     if ((*it)->synchronous())
   1298       return true;
   1299   }
   1300   return false;
   1301 }
   1302