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