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