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