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
59using content::NavigationController;
60using content::RenderWidgetHost;
61using content::WebContents;
62
63namespace {
64
65class SessionRestoreImpl;
66class TabLoader;
67
68TabLoader* shared_tab_loader = NULL;
69
70// Pointers to SessionRestoreImpls which are currently restoring the session.
71std::set<SessionRestoreImpl*>* active_session_restorers = NULL;
72
73// TabLoader ------------------------------------------------------------------
74
75// Initial delay (see class decription for details).
76static 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.
91class 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
202TabLoader* 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
208void 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
217void 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
229void 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
254TabLoader::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
263TabLoader::~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
270void 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
315void 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
400void 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
412void 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
430void TabLoader::ForceLoadTimerFired() {
431  force_load_delay_ *= 2;
432  LoadNextTab();
433}
434
435RenderWidgetHost* 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
446void 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
456void 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
486void 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
514class 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
1203Browser* 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
1232void 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
1250std::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
1262WebContents* 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
1275bool 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
1288bool 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