15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_restore.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_vector.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/platform_file.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/performance_monitor/startup_timer.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_service.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_service_factory.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_types.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_navigator.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_tabrestore.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_tabstrip.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
37558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/cancelable_task_tracker.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/child_process_security_policy.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/dom_storage_context.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_widget_host.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_widget_host_view.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/session_storage_namespace.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/storage_partition.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/network_change_notifier.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/boot_times_loader.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "win8/util/win8_util.h"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_ASH)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_util.h"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderWidgetHost;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SessionRestoreImpl;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TabLoader;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabLoader* shared_tab_loader = NULL;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pointers to SessionRestoreImpls which are currently restoring the session.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::set<SessionRestoreImpl*>* active_session_restorers = NULL;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabLoader ------------------------------------------------------------------
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initial delay (see class decription for details).
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kInitialDelayTimerMS = 100;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabLoader is responsible for loading tabs after session restore creates
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tabs. New tabs are loaded after the current tab finishes loading, or a delay
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is reached (initially kInitialDelayTimerMS). If the delay is reached before
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a tab finishes loading a new tab is loaded and the time of the delay
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// doubled.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabLoader keeps a reference to itself when it's loading. When it has finished
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// loading, it drops the reference. If another profile is restored while the
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabLoader is loading, it will schedule its tabs to get loaded by the same
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabLoader. When doing the scheduling, it holds a reference to the TabLoader.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is not part of SessionRestoreImpl so that synchronous destruction
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of SessionRestoreImpl doesn't have timing problems.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TabLoader : public content::NotificationObserver,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  public net::NetworkChangeNotifier::ConnectionTypeObserver,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  public base::RefCounted<TabLoader> {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieves a pointer to the TabLoader instance shared between profiles, or
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // creates a new TabLoader if it doesn't exist. If a TabLoader is created, its
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // starting timestamp is set to |restore_started|.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static TabLoader* GetTabLoader(base::TimeTicks restore_started);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules a tab for loading.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ScheduleLoad(NavigationController* controller);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the loader that a tab has been scheduled for loading through
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // some other mechanism.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TabIsLoading(NavigationController* controller);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invokes |LoadNextTab| to load a tab.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This must be invoked once to start loading.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartLoading();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCounted<TabLoader>;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::set<NavigationController*> TabsLoading;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::list<NavigationController*> TabsToLoad;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::set<RenderWidgetHost*> RenderWidgetHostSet;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TabLoader(base::TimeTicks restore_started);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TabLoader();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loads the next tab. If there are no more tabs to load this deletes itself,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // otherwise |force_load_timer_| is restarted.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void LoadNextTab();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NotificationObserver method. Removes the specified tab and loads the next
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tab.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // net::NetworkChangeNotifier::ConnectionTypeObserver overrides.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnConnectionTypeChanged(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Removes the listeners from the specified tab and removes the tab from
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the set of tabs to load and list of tabs we're waiting to get a load
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveTab(NavigationController* tab);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoked from |force_load_timer_|. Doubles |force_load_delay_| and invokes
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |LoadNextTab| to load the next tab
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ForceLoadTimerFired();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the RenderWidgetHost associated with a tab if there is one,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NULL otherwise.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static RenderWidgetHost* GetRenderWidgetHost(NavigationController* tab);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register for necessary notifications on a tab navigation controller.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RegisterForNotifications(NavigationController* controller);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when a tab goes away or a load completes.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleTabClosedOrLoaded(NavigationController* controller);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Current delay before a new tab is loaded. See class description for
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // details.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 force_load_delay_;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Has Load been invoked?
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool loading_;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Have we recorded the times for a tab paint?
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool got_first_paint_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The set of tabs we've initiated loading on. This does NOT include the
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // selected tabs.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabsLoading tabs_loading_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The tabs we need to load.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabsToLoad tabs_to_load_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The renderers we have started loading into.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderWidgetHostSet render_widget_hosts_loading_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The renderers we have loaded and are waiting on to paint.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderWidgetHostSet render_widget_hosts_to_paint_;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The number of tabs that have been restored.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tab_count_;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<TabLoader> force_load_timer_;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The time the restore process started.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks restore_started_;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Max number of tabs that were loaded in parallel (for metrics).
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t max_parallel_tab_loads_;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For keeping TabLoader alive while it's loading even if no
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SessionRestoreImpls reference it.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TabLoader> this_retainer_;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TabLoader);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabLoader* TabLoader::GetTabLoader(base::TimeTicks restore_started) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!shared_tab_loader)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shared_tab_loader = new TabLoader(restore_started);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return shared_tab_loader;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::ScheduleLoad(NavigationController* controller) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(controller);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) ==
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         tabs_to_load_.end());
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tabs_to_load_.push_back(controller);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisterForNotifications(controller);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::TabIsLoading(NavigationController* controller) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(controller);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(find(tabs_loading_.begin(), tabs_loading_.end(), controller) ==
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         tabs_loading_.end());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tabs_loading_.insert(controller);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderWidgetHost* render_widget_host = GetRenderWidgetHost(controller);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(render_widget_host);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_widget_hosts_loading_.insert(render_widget_host);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisterForNotifications(controller);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::StartLoading() {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When multiple profiles are using the same TabLoader, another profile might
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already have started loading. In that case, the tabs scheduled for loading
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by this profile are already in the loading queue, and they will get loaded
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // eventually.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loading_)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this_retainer_ = this;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!net::NetworkChangeNotifier::IsOffline()) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loading_ = true;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadNextTab();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loading_ = true;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadNextTab();
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabLoader::TabLoader(base::TimeTicks restore_started)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : force_load_delay_(kInitialDelayTimerMS),
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loading_(false),
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      got_first_paint_(false),
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_count_(0),
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restore_started_(restore_started),
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_parallel_tab_loads_(0) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabLoader::~TabLoader() {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tabs_loading_.empty() && tabs_to_load_.empty());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shared_tab_loader = NULL;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::LoadNextTab() {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tabs_to_load_.empty()) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NavigationController* tab = tabs_to_load_.front();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(tab);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tabs_loading_.insert(tab);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tabs_loading_.size() > max_parallel_tab_loads_)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_parallel_tab_loads_ = tabs_loading_.size();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tabs_to_load_.pop_front();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab->LoadIfNecessary();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::WebContents* contents = tab->GetWebContents();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (contents) {
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Browser* browser = chrome::FindBrowserWithWebContents(contents);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (browser &&
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          browser->tab_strip_model()->GetActiveWebContents() != contents) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // By default tabs are marked as visible. As only the active tab is
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // visible we need to explicitly tell non-active tabs they are hidden.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Without this call non-active tabs are not marked as backgrounded.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // NOTE: We need to do this here rather than when the tab is added to
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the Browser as at that time not everything has been created, so that
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the call would do nothing.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        contents->WasHidden();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tabs_to_load_.empty()) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    force_load_timer_.Stop();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Each time we load a tab we also set a timer to force us to start loading
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the next tab if this one doesn't load quickly enough.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    force_load_timer_.Start(FROM_HERE,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(force_load_delay_),
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this, &TabLoader::ForceLoadTimerFired);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // When the session restore is done synchronously, notification is sent from
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // SessionRestoreImpl::Restore .
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (tabs_to_load_.empty() && !SessionRestore::IsRestoringSynchronously()) {
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    content::NotificationService::current()->Notify(
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        chrome::NOTIFICATION_SESSION_RESTORE_DONE,
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        content::NotificationService::AllSources(),
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        content::NotificationService::NoDetails());
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::Observe(int type,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const content::NotificationSource& source,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const content::NotificationDetails& details) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_LOAD_START: {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Add this render_widget_host to the set of those we're waiting for
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // paints on. We want to only record stats for paints that occur after
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // a load has finished.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NavigationController* tab =
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<NavigationController>(source).ptr();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(render_widget_host);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_widget_hosts_loading_.insert(render_widget_host);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebContents* web_contents = content::Source<WebContents>(source).ptr();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!got_first_paint_) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RenderWidgetHost* render_widget_host =
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GetRenderWidgetHost(&web_contents->GetController());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_widget_hosts_loading_.erase(render_widget_host);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleTabClosedOrLoaded(&web_contents->GetController());
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_LOAD_STOP: {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NavigationController* tab =
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<NavigationController>(source).ptr();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_widget_hosts_to_paint_.insert(GetRenderWidgetHost(tab));
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleTabClosedOrLoaded(tab);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RenderWidgetHost* render_widget_host =
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<RenderWidgetHost>(source).ptr();
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!got_first_paint_ && render_widget_host->GetView() &&
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          render_widget_host->GetView()->IsShowing()) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (render_widget_hosts_to_paint_.find(render_widget_host) !=
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_widget_hosts_to_paint_.end()) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Got a paint for one of our renderers, so record time.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          got_first_paint_ = true;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::TimeDelta time_to_paint =
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              base::TimeTicks::Now() - restore_started_;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          UMA_HISTOGRAM_CUSTOM_TIMES(
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "SessionRestore.FirstTabPainted",
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              time_to_paint,
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              base::TimeDelta::FromMilliseconds(10),
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              base::TimeDelta::FromSeconds(100),
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              100);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Record a time for the number of tabs, to help track down
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // contention.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          std::string time_for_count =
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              base::StringPrintf("SessionRestore.FirstTabPainted_%d",
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 tab_count_);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::HistogramBase* counter_for_count =
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              base::Histogram::FactoryTimeGet(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  time_for_count,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  base::TimeDelta::FromMilliseconds(10),
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  base::TimeDelta::FromSeconds(100),
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  100,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  base::Histogram::kUmaTargetedHistogramFlag);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          counter_for_count->AddTime(time_to_paint);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (render_widget_hosts_loading_.find(render_widget_host) ==
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_widget_hosts_loading_.end()) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // If this is a host for a tab we're not loading some other tab
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // has rendered and there's no point tracking the time. This could
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // happen because the user opened a different tab or restored tabs
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // to an already existing browser and an existing tab painted.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          got_first_paint_ = true;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unknown notification received:" << type;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete ourselves when we're not waiting for any more notifications. If this
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was not the last reference, a SessionRestoreImpl holding a reference will
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // eventually call StartLoading (which assigns this_retainer_), or drop the
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference without initiating a load.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tabs_loading_.empty() && tabs_to_load_.empty())
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this_retainer_ = NULL;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::OnConnectionTypeChanged(
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkChangeNotifier::ConnectionType type) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type != net::NetworkChangeNotifier::CONNECTION_NONE) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!loading_) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loading_ = true;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadNextTab();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loading_ = false;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::RemoveTab(NavigationController* tab) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    content::Source<WebContents>(tab->GetWebContents()));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    content::Source<NavigationController>(tab));
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Remove(this, content::NOTIFICATION_LOAD_START,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    content::Source<NavigationController>(tab));
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabsLoading::iterator i = tabs_loading_.find(tab);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != tabs_loading_.end())
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tabs_loading_.erase(i);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabsToLoad::iterator j =
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      find(tabs_to_load_.begin(), tabs_to_load_.end(), tab);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (j != tabs_to_load_.end())
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tabs_to_load_.erase(j);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::ForceLoadTimerFired() {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  force_load_delay_ *= 2;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadNextTab();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RenderWidgetHost* TabLoader::GetRenderWidgetHost(NavigationController* tab) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* web_contents = tab->GetWebContents();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (web_contents) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderWidgetHostView* render_widget_host_view =
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        web_contents->GetRenderWidgetHostView();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (render_widget_host_view)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return render_widget_host_view->GetRenderWidgetHost();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::RegisterForNotifications(NavigationController* controller) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::Source<WebContents>(controller->GetWebContents()));
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::Source<NavigationController>(controller));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_LOAD_START,
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::Source<NavigationController>(controller));
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++tab_count_;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabLoader::HandleTabClosedOrLoaded(NavigationController* tab) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveTab(tab);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loading_)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadNextTab();
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tabs_loading_.empty() && tabs_to_load_.empty()) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta time_to_load =
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeTicks::Now() - restore_started_;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    performance_monitor::StartupTimer::SetElapsedSessionRestoreTime(
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        time_to_load);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SessionRestore.AllTabsLoaded",
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        time_to_load,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(10),
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(100),
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        100);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Record a time for the number of tabs, to help track down contention.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string time_for_count =
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_);
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::HistogramBase* counter_for_count =
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Histogram::FactoryTimeGet(
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            time_for_count,
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::TimeDelta::FromMilliseconds(10),
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::TimeDelta::FromSeconds(100),
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            100,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::Histogram::kUmaTargetedHistogramFlag);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    counter_for_count->AddTime(time_to_load);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads",
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             max_parallel_tab_loads_);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SessionRestoreImpl ---------------------------------------------------------
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SessionRestoreImpl is responsible for fetching the set of tabs to create
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from SessionService. SessionRestoreImpl deletes itself when done.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SessionRestoreImpl : public content::NotificationObserver {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionRestoreImpl(Profile* profile,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     Browser* browser,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     chrome::HostDesktopType host_desktop_type,
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     bool synchronous,
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     bool clobber_existing_tab,
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     bool always_create_tabbed_browser,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::vector<GURL>& urls_to_open)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : profile_(profile),
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser_(browser),
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        host_desktop_type_(host_desktop_type),
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        synchronous_(synchronous),
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        clobber_existing_tab_(clobber_existing_tab),
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        always_create_tabbed_browser_(always_create_tabbed_browser),
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        urls_to_open_(urls_to_open),
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        active_window_id_(0),
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        restore_started_(base::TimeTicks::Now()),
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser_shown_(false) {
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // For sanity's sake, if |browser| is non-null: force |host_desktop_type| to
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // be the same as |browser|'s desktop type.
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!browser || browser->host_desktop_type() == host_desktop_type);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (active_session_restorers == NULL)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_session_restorers = new std::set<SessionRestoreImpl*>();
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only one SessionRestoreImpl should be operating on the profile at the
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // same time.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<SessionRestoreImpl*>::const_iterator it;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (it = active_session_restorers->begin();
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != active_session_restorers->end(); ++it) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*it)->profile_ == profile)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(it == active_session_restorers->end());
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_session_restorers->insert(this);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When asynchronous its possible for there to be no windows. To make sure
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Chrome doesn't prematurely exit AddRef the process. We'll release in the
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // destructor when restore is done.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_browser_process->AddRefModule();
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool synchronous() const { return synchronous_; }
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* Restore() {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionService* session_service =
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionServiceFactory::GetForProfile(profile_);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(session_service);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_service->GetLastSession(
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&SessionRestoreImpl::OnGotSession, base::Unretained(this)),
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &cancelable_task_tracker_);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (synchronous_) {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
54990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::MessageLoop::ScopedNestableTaskAllower allow(
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            base::MessageLoop::current());
55190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::MessageLoop::current()->Run();
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Browser* browser = ProcessSessionWindows(&windows_, active_window_id_);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete this;
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::NotificationService::current()->Notify(
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          chrome::NOTIFICATION_SESSION_RESTORE_DONE,
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          content::NotificationService::AllSources(),
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          content::NotificationService::NoDetails());
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return browser;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (browser_) {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     content::Source<Browser>(browser_));
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return browser_;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Restore window(s) from a foreign session. Returns newly created Browsers.
5713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  std::vector<Browser*> RestoreForeignSession(
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<const SessionWindow*>::const_iterator begin,
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<const SessionWindow*>::const_iterator end) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartTabCreation();
5753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::vector<Browser*> browsers;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a browser instance to put the restored tabs in.
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<const SessionWindow*>::const_iterator i = begin;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         i != end; ++i) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Browser* browser = CreateRestoredBrowser(
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<Browser::Type>((*i)->type),
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*i)->bounds,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*i)->show_state,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*i)->app_name);
5843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      browsers.push_back(browser);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Restore and show the browser.
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int initial_tab_count = 0;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int selected_tab_index = std::max(
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          0,
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          std::min((*i)->selected_tab_index,
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   static_cast<int>((*i)->tabs.size()) - 1));
59290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RestoreTabsToBrowser(*(*i), browser, initial_tab_count,
59390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                           selected_tab_index);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Always create in a new window
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FinishedTabCreation(true, true);
5993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return browsers;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore a single tab from a foreign session.
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Opens in the tab in the last active browser, unless disposition is
6043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // NEW_WINDOW, in which case the tab will be opened in a new browser. Returns
6053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // the WebContents of the restored tab.
6063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  WebContents* RestoreForeignTab(const SessionTab& tab,
6073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                 WindowOpenDisposition disposition) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!tab.navigations.empty());
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int selected_index = tab.current_navigation_index;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    selected_index = std::max(
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0,
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(selected_index,
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 static_cast<int>(tab.navigations.size() - 1)));
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool use_new_window = disposition == NEW_WINDOW;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser = use_new_window ?
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new Browser(Browser::CreateParams(profile_, host_desktop_type_)) :
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        browser_;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RecordAppLaunchForTab(browser, tab, selected_index);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    WebContents* web_contents;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (disposition == CURRENT_TAB) {
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!use_new_window);
6263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      web_contents = chrome::ReplaceRestoredTab(browser,
6273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                                tab.navigations,
6283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                                selected_index,
6293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                                true,
6303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                                tab.extension_app_id,
6313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                                NULL,
6323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                                tab.user_agent_override);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int tab_index =
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          use_new_window ? 0 : browser->tab_strip_model()->active_index() + 1;
6363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      web_contents = chrome::AddRestoredTab(
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          browser,
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tab.navigations,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tab_index,
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          selected_index,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tab.extension_app_id,
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          disposition == NEW_FOREGROUND_TAB,  // selected
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tab.pinned,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          true,
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL,
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tab.user_agent_override);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Start loading the tab immediately.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      web_contents->GetController().LoadIfNecessary();
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_new_window) {
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser->tab_strip_model()->ActivateTabAt(0, true);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser->window()->Show();
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifySessionServiceOfRestoredTabs(browser,
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       browser->tab_strip_model()->count());
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since FinishedTabCreation() is not called here, |this| will leak if we
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // are not in sychronous mode.
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(synchronous_);
6613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return web_contents;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SessionRestoreImpl() {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLDeleteElements(&windows_);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_session_restorers->erase(this);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (active_session_restorers->empty()) {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete active_session_restorers;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_session_restorers = NULL;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_browser_process->ReleaseModule();
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (type) {
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case chrome::NOTIFICATION_BROWSER_CLOSED:
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete this;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile() { return profile_; }
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoked when beginning to create new tabs. Resets the tab_loader_.
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartTabCreation() {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab_loader_ = TabLoader::GetTabLoader(restore_started_);
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoked when done with creating all the tabs/browsers.
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |created_tabbed_browser| indicates whether a tabbed browser was created,
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or we used an existing tabbed browser.
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If successful, this begins loading tabs and deletes itself when all tabs
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have been loaded.
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the Browser that was created, if any.
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* FinishedTabCreation(bool succeeded, bool created_tabbed_browser) {
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser = NULL;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!created_tabbed_browser && always_create_tabbed_browser_) {
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser = new Browser(Browser::CreateParams(profile_,
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  host_desktop_type_));
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (urls_to_open_.empty()) {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // No tab browsers were created and no URLs were supplied on the command
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // line. Add an empty URL, which is treated as opening the users home
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // page.
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        urls_to_open_.push_back(GURL());
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppendURLsToBrowser(browser, urls_to_open_);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser->window()->Show();
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (succeeded) {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(tab_loader_.get());
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TabLoader deletes itself when done loading.
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_loader_->StartLoading();
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_loader_ = NULL;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!synchronous_) {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we're not synchronous we need to delete ourself.
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // NOTE: we must use DeleteLater here as most likely we're in a callback
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // from the history service which doesn't deal well with deleting the
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // object it is notifying.
73490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // The delete may take a while and at this point we no longer care about
737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // if the browser is deleted. Don't listen to anything. This avoid a
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // possible double delete too (if browser is closed before DeleteSoon() is
739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // processed).
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      registrar_.RemoveAll();
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SessionRestore-End", false);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return browser;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnGotSession(ScopedVector<SessionWindow> windows,
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    SessionID::id_type active_window_id) {
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta time_to_got_sessions =
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeTicks::Now() - restore_started_;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SessionRestore.TimeToGotSessions",
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        time_to_got_sessions,
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(10),
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(1000),
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        100);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SessionRestore-GotSession", false);
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (synchronous_) {
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See comment above windows_ as to why we don't process immediately.
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      windows_.swap(windows.get());
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_window_id_ = active_window_id;
76890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->QuitNow();
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProcessSessionWindows(&windows.get(), active_window_id);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* ProcessSessionWindows(std::vector<SessionWindow*>* windows,
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 SessionID::id_type active_window_id) {
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "ProcessSessionWindows " << windows->size();
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta time_to_process_sessions =
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeTicks::Now() - restore_started_;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_TIMES(
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SessionRestore.TimeToProcessSessions",
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        time_to_process_sessions,
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(10),
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(1000),
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        100);
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (windows->empty()) {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Restore was unsuccessful. The DOM storage system can also delete its
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // data, since no session restore will happen at a later point in time.
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::BrowserContext::GetDefaultStoragePartition(profile_)->
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetDOMStorageContext()->StartScavengingUnusedSessionStorage();
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return FinishedTabCreation(false, false);
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SessionRestore-CreatingTabs-Start", false);
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartTabCreation();
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // After the for loop this contains the last TABBED_BROWSER. Is null if no
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // tabbed browsers exist.
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* last_browser = NULL;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_tabbed_browser = false;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // After the for loop, this contains the browser to activate, if one of the
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // windows has the same id as specified in active_window_id.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser_to_activate = NULL;
80990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_WIN)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int selected_tab_to_activate = -1;
81190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Determine if there is a visible window.
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_visible_browser = false;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<SessionWindow*>::iterator i = windows->begin();
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         i != windows->end(); ++i) {
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*i)->show_state != ui::SHOW_STATE_MINIMIZED)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        has_visible_browser = true;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<SessionWindow*>::iterator i = windows->begin();
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         i != windows->end(); ++i) {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Browser* browser = NULL;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!has_tabbed_browser && (*i)->type == Browser::TYPE_TABBED)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        has_tabbed_browser = true;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i == windows->begin() && (*i)->type == Browser::TYPE_TABBED &&
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          browser_ && browser_->is_type_tabbed() &&
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !browser_->profile()->IsOffTheRecord()) {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The first set of tabs is added to the existing browser.
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser = browser_;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SessionRestore-CreateRestoredBrowser-Start", false);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Show the first window if none are visible.
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::WindowShowState show_state = (*i)->show_state;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!has_visible_browser) {
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          show_state = ui::SHOW_STATE_NORMAL;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          has_visible_browser = true;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser = NULL;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (win8::IsSingleWindowMetroMode()) {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // We don't want to add tabs to the off the record browser.
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (browser_ && !browser_->profile()->IsOffTheRecord()) {
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            browser = browser_;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            browser = last_browser;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // last_browser should never be off the record either.
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // We don't set browser higher above when browser_ is offtherecord,
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // and CreateRestoredBrowser below, is never created offtherecord.
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DCHECK(!browser || !browser->profile()->IsOffTheRecord());
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Metro should only have tabbed browsers.
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // It never creates any non-tabbed browser, and thus should never
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // restore non-tabbed items...
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK(!browser || browser->is_type_tabbed());
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK((*i)->type == Browser::TYPE_TABBED);
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!browser) {
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          browser = CreateRestoredBrowser(
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              static_cast<Browser::Type>((*i)->type),
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (*i)->bounds,
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              show_state,
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (*i)->app_name);
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SessionRestore-CreateRestoredBrowser-End", false);
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*i)->type == Browser::TYPE_TABBED)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_browser = browser;
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      WebContents* active_tab =
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          browser->tab_strip_model()->GetActiveWebContents();
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int initial_tab_count = browser->tab_strip_model()->count();
87990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bool close_active_tab = clobber_existing_tab_ &&
88090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              i == windows->begin() &&
88190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              (*i)->type == Browser::TYPE_TABBED &&
88290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              active_tab && browser == browser_ &&
88390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              (*i)->tabs.size() > 0;
88490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (close_active_tab)
88590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        --initial_tab_count;
88690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int selected_tab_index =
88790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          initial_tab_count > 0 ? browser->tab_strip_model()->active_index()
88890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                : std::max(0,
88990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    std::min((*i)->selected_tab_index,
89090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    static_cast<int>((*i)->tabs.size()) - 1));
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*i)->window_id.id() == active_window_id) {
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser_to_activate = browser;
89390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_WIN)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        selected_tab_to_activate = selected_tab_index;
89590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
89790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RestoreTabsToBrowser(*(*i), browser, initial_tab_count,
89890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                           selected_tab_index);
89990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
90090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // This needs to be done after restore because closing the last tab will
90190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // close the whole window.
90290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (close_active_tab)
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        chrome::CloseWebContents(browser, active_tab, true);
90490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_WIN)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        selected_tab_to_activate = -1;
90690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (browser_to_activate && browser_to_activate->is_type_tabbed())
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_browser = browser_to_activate;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (last_browser && !urls_to_open_.empty())
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppendURLsToBrowser(last_browser, urls_to_open_);
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SessionRestore-CreatingTabs-End", false);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (browser_to_activate) {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_to_activate->window()->Activate();
92090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_WIN)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // On Win8 Metro, we merge all browsers together, so if we need to
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // activate one of the previously separated window, we need to activate
92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // the tab. Also, selected_tab_to_activate can be -1 if we clobbered the
92490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // tab that would have been activated.
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // In that case we'll leave activation to last tab.
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The only current usage of clobber is for crash recovery, so it's fine.
92790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (win8::IsSingleWindowMetroMode() && selected_tab_to_activate != -1)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ShowBrowser(browser_to_activate, selected_tab_to_activate);
92990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If last_browser is NULL and urls_to_open_ is non-empty,
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // FinishedTabCreation will create a new TabbedBrowser and add the urls to
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it.
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* finished_browser = FinishedTabCreation(true, has_tabbed_browser);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (finished_browser)
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_browser = finished_browser;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sessionStorages needed for the session restore have now been recreated
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // by RestoreTab. Now it's safe for the DOM storage system to start
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // deleting leftover data.
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::BrowserContext::GetDefaultStoragePartition(profile_)->
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetDOMStorageContext()->StartScavengingUnusedSessionStorage();
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return last_browser;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record an app launch event (if appropriate) for a tab which is about to
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be restored. Callers should ensure that selected_index is within the
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bounds of tab.navigations before calling.
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordAppLaunchForTab(Browser* browser,
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const SessionTab& tab,
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int selected_index) {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(selected_index >= 0 &&
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           selected_index < static_cast<int>(tab.navigations.size()));
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL url = tab.navigations[selected_index].virtual_url();
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (browser->profile()->GetExtensionService()) {
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const extensions::Extension* extension =
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          browser->profile()->GetExtensionService()->GetInstalledApp(url);
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (extension) {
960558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        CoreAppLauncherHandler::RecordAppLaunchType(
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            extension_misc::APP_LAUNCH_SESSION_RESTORE,
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            extension->GetType());
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
96790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Adds the tabs from |window| to |browser|. Normal tabs go after the existing
96890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tabs but pinned tabs will be pushed in front.
96990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If there are no existing tabs, the tab at |selected_tab_index| will be
97090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // selected. Otherwise, the tab selection will remain untouched.
97190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void RestoreTabsToBrowser(const SessionWindow& window,
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           Browser* browser,
97390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                           int initial_tab_count,
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int selected_tab_index) {
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "RestoreTabsToBrowser " << window.tabs.size();
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!window.tabs.empty());
97790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (initial_tab_count == 0) {
97890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
97990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        const SessionTab& tab = *(window.tabs[i]);
98090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Loads are scheduled for each restored tab unless the tab is going to
98190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // be selected as ShowBrowser() will load the selected tab.
98290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (i == selected_tab_index) {
98390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          ShowBrowser(browser,
98490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      browser->tab_strip_model()->GetIndexOfWebContents(
98590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          RestoreTab(tab, i, browser, false)));
98690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          tab_loader_->TabIsLoading(
98790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              &browser->tab_strip_model()->GetActiveWebContents()->
98890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  GetController());
98990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        } else {
99090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          RestoreTab(tab, i, browser, true);
99190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
99290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
99390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
99490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // If the browser already has tabs, we want to restore the new ones after
99590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // the existing ones. E.g. this happens in Win8 Metro where we merge
99690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // windows or when launching a hosted app from the app launcher.
99790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int tab_index_offset = initial_tab_count;
99890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
99990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        const SessionTab& tab = *(window.tabs[i]);
100090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Always schedule loads as we will not be calling ShowBrowser().
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RestoreTab(tab, tab_index_offset + i, browser, true);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
100690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // |tab_index| is ignored for pinned tabs which will always be pushed behind
100790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // the last existing pinned tab.
100890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // |schedule_load| will let |tab_loader_| know that it should schedule this
100990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tab for loading.
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* RestoreTab(const SessionTab& tab,
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const int tab_index,
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          Browser* browser,
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          bool schedule_load) {
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It's possible (particularly for foreign sessions) to receive a tab
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // without valid navigations. In that case, just skip it.
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See crbug.com/154129.
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tab.navigations.empty())
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int selected_index = tab.current_navigation_index;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    selected_index = std::max(
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0,
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::min(selected_index,
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 static_cast<int>(tab.navigations.size() - 1)));
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RecordAppLaunchForTab(browser, tab, selected_index);
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Associate sessionStorage (if any) to the restored tab.
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<content::SessionStorageNamespace> session_storage_namespace;
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!tab.session_storage_persistent_id.empty()) {
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_storage_namespace =
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::BrowserContext::GetDefaultStoragePartition(profile_)->
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetDOMStorageContext()->RecreateSessionStorage(
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  tab.session_storage_persistent_id);
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebContents* web_contents =
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome::AddRestoredTab(browser,
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               tab.navigations,
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               tab_index,
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               selected_index,
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               tab.extension_app_id,
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               false,  // select
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               tab.pinned,
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               true,
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               session_storage_namespace.get(),
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               tab.user_agent_override);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Regression check: check that the tab didn't start loading right away. The
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // focused tab will be loaded by Browser, and TabLoader will load the rest.
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(web_contents->GetController().NeedsReload());
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set up the file access rights for the selected navigation entry.
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int id = web_contents->GetRenderProcessHost()->GetID();
105390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const content::PageState& page_state =
105490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        tab.navigations.at(selected_index).page_state();
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<base::FilePath>& file_paths =
105690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        page_state.GetReferencedFiles();
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (std::vector<base::FilePath>::const_iterator file = file_paths.begin();
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         file != file_paths.end(); ++file) {
10597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(id,
10607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                                        *file);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (schedule_load)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_loader_->ScheduleLoad(&web_contents->GetController());
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return web_contents;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* CreateRestoredBrowser(Browser::Type type,
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 gfx::Rect bounds,
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 ui::WindowShowState show_state,
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& app_name) {
10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser::CreateParams params(type, profile_, host_desktop_type_);
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    params.app_name = app_name;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    params.initial_bounds = bounds;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    params.initial_show_state = show_state;
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    params.is_session_restore = true;
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new Browser(params);
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ShowBrowser(Browser* browser, int selected_tab_index) {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(browser);
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(browser->tab_strip_model()->count());
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser->tab_strip_model()->ActivateTabAt(selected_tab_index, true);
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (browser_ == browser)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_ASH)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Prevent the auto window management for this window on show.
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ash::wm::SetUserHasChangedWindowPositionOrSize(
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->window()->GetNativeWindow(), true);
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser->window()->Show();
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_ASH)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ash::wm::SetUserHasChangedWindowPositionOrSize(
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->window()->GetNativeWindow(), false);
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser->set_is_session_restore(false);
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(jcampan): http://crbug.com/8123 we should not need to set the
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //                initial focus explicitly.
11022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser->tab_strip_model()->GetActiveWebContents()->
11032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetView()->SetInitialFocus();
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!browser_shown_) {
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_shown_ = true;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta time_to_first_show =
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::TimeTicks::Now() - restore_started_;
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_CUSTOM_TIMES(
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "SessionRestore.TimeToFirstShow",
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          time_to_first_show,
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::TimeDelta::FromMilliseconds(10),
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::TimeDelta::FromSeconds(1000),
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          100);
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Appends the urls in |urls| to |browser|.
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AppendURLsToBrowser(Browser* browser,
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const std::vector<GURL>& urls) {
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < urls.size(); ++i) {
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int add_types = TabStripModel::ADD_FORCE_INDEX;
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i == 0)
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_types |= TabStripModel::ADD_ACTIVE;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NavigateParams params(browser, urls[i],
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    content::PAGE_TRANSITION_AUTO_TOPLEVEL);
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params.disposition = i == 0 ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params.tabstrip_add_types = add_types;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::Navigate(&params);
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invokes TabRestored on the SessionService for all tabs in browser after
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initial_count.
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifySessionServiceOfRestoredTabs(Browser* browser, int initial_count) {
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionService* session_service =
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SessionServiceFactory::GetForProfile(profile_);
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!session_service)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TabStripModel* tab_strip = browser->tab_strip_model();
11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = initial_count; i < tab_strip->count(); ++i)
11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session_service->TabRestored(tab_strip->GetWebContentsAt(i),
11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   tab_strip->IsTabPinned(i));
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The profile to create the sessions for.
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile_;
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first browser to restore to, may be null.
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* browser_;
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The desktop on which all new browsers should be created (browser_, if it is
11532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // not NULL, must be of this desktop type as well).
11542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::HostDesktopType host_desktop_type_;
11552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether or not restore is synchronous.
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool synchronous_;
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See description of CLOBBER_CURRENT_TAB.
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool clobber_existing_tab_;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If true and there is an error or there are no windows to restore, we
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // create a tabbed browser anyway. This is used on startup to make sure at
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // at least one window is created.
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool always_create_tabbed_browser_;
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set of URLs to open in addition to those restored from the session.
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<GURL> urls_to_open_;
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used to get the session.
11712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CancelableTaskTracker cancelable_task_tracker_;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responsible for loading the tabs.
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TabLoader> tab_loader_;
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When synchronous we run a nested message loop. To avoid creating windows
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the nested message loop (which can make exiting the nested message
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // loop take a while) we cache the SessionWindows here and create the actual
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // windows when the nested message loop exits.
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SessionWindow*> windows_;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionID::id_type active_window_id_;
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The time we started the restore.
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks restore_started_;
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to true after the first browser is shown.
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool browser_shown_;
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SessionRestoreImpl);
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SessionRestore -------------------------------------------------------------
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
11992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Browser* SessionRestore::RestoreSession(
12002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Profile* profile,
12012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser,
12022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::HostDesktopType host_desktop_type,
12032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32 behavior,
12042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<GURL>& urls_to_open) {
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "SessionRestore-Start", false);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile);
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always restore from the original profile (incognito profiles have no
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // session service).
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile = profile->GetOriginalProfile();
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SessionServiceFactory::GetForProfile(profile)) {
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile->set_restored_last_session(true);
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SessionRestoreImpl takes care of deleting itself when done.
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionRestoreImpl* restorer = new SessionRestoreImpl(
12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile, browser, host_desktop_type, (behavior & SYNCHRONOUS) != 0,
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (behavior & CLOBBER_CURRENT_TAB) != 0,
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (behavior & ALWAYS_CREATE_TABBED_BROWSER) != 0,
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      urls_to_open);
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return restorer->Restore();
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
12283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::vector<Browser*> SessionRestore::RestoreForeignSessionWindows(
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::HostDesktopType host_desktop_type,
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<const SessionWindow*>::const_iterator begin,
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<const SessionWindow*>::const_iterator end) {
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<GURL> gurls;
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionRestoreImpl restorer(profile,
12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<Browser*>(NULL), host_desktop_type, true, false, true, gurls);
12363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return restorer.RestoreForeignSession(begin, end);
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
12403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochWebContents* SessionRestore::RestoreForeignSessionTab(
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::WebContents* source_web_contents,
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionTab& tab,
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WindowOpenDisposition disposition) {
12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Browser* browser = chrome::FindBrowserWithWebContents(source_web_contents);
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = browser->profile();
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<GURL> gurls;
12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SessionRestoreImpl restorer(profile, browser, browser->host_desktop_type(),
12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              true, false, false, gurls);
12493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return restorer.RestoreForeignTab(tab, disposition);
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SessionRestore::IsRestoring(const Profile* profile) {
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_session_restorers == NULL)
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<SessionRestoreImpl*>::const_iterator it =
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           active_session_restorers->begin();
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != active_session_restorers->end(); ++it) {
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->profile() == profile)
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SessionRestore::IsRestoringSynchronously() {
12672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!active_session_restorers)
12682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
12692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::set<SessionRestoreImpl*>::const_iterator it =
12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           active_session_restorers->begin();
12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != active_session_restorers->end(); ++it) {
12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*it)->synchronous())
12732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
12742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
12762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1277