1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/metrics/user_metrics_action.h"
6#include "base/supports_user_data.h"
7#include "chrome/browser/profiles/profile.h"
8#include "chrome/browser/sessions/tab_restore_service.h"
9#include "chrome/browser/sessions/tab_restore_service_factory.h"
10#include "chrome/browser/sessions/tab_restore_service_observer.h"
11#include "chrome/browser/ui/browser.h"
12#include "chrome/browser/ui/browser_commands.h"
13#include "chrome/browser/ui/browser_list.h"
14#include "chrome/browser/ui/browser_list_observer.h"
15#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
16#include "content/public/browser/user_metrics.h"
17
18namespace chrome {
19namespace {
20
21const char kBrowserTabRestorerKey[] = "BrowserTabRestorer";
22
23// BrowserTabRestorer is responsible for restoring a tab when the
24// TabRestoreService finishes loading. A TabRestoreService is associated with a
25// single Browser and deletes itself if the Browser is destroyed.
26// BrowserTabRestorer is installed on the Profile (by way of user data), only
27// one instance is created per profile at a time.
28class BrowserTabRestorer : public TabRestoreServiceObserver,
29                           public chrome::BrowserListObserver,
30                           public base::SupportsUserData::Data {
31 public:
32  virtual ~BrowserTabRestorer();
33
34  static void CreateIfNecessary(Browser* browser);
35
36 private:
37  explicit BrowserTabRestorer(Browser* browser);
38
39  // TabRestoreServiceObserver:
40  virtual void TabRestoreServiceChanged(TabRestoreService* service) OVERRIDE;
41  virtual void TabRestoreServiceDestroyed(TabRestoreService* service) OVERRIDE;
42  virtual void TabRestoreServiceLoaded(TabRestoreService* service) OVERRIDE;
43
44  // BrowserListObserver:
45  virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
46
47  Browser* browser_;
48  TabRestoreService* tab_restore_service_;
49
50  DISALLOW_COPY_AND_ASSIGN(BrowserTabRestorer);
51};
52
53BrowserTabRestorer::~BrowserTabRestorer() {
54  tab_restore_service_->RemoveObserver(this);
55  BrowserList::GetInstance(browser_->host_desktop_type())->RemoveObserver(this);
56}
57
58// static
59void BrowserTabRestorer::CreateIfNecessary(Browser* browser) {
60  DCHECK(browser);
61  if (browser->profile()->GetUserData(kBrowserTabRestorerKey))
62    return;  // Only allow one restore for a given profile at a time.
63
64  // BrowserTabRestorer is deleted at the appropriate time.
65  new BrowserTabRestorer(browser);
66}
67
68BrowserTabRestorer::BrowserTabRestorer(Browser* browser)
69    : browser_(browser),
70      tab_restore_service_(
71          TabRestoreServiceFactory::GetForProfile(browser->profile())) {
72  DCHECK(tab_restore_service_);
73  DCHECK(!tab_restore_service_->IsLoaded());
74  tab_restore_service_->AddObserver(this);
75  BrowserList::GetInstance(browser->host_desktop_type())->AddObserver(this);
76  browser_->profile()->SetUserData(kBrowserTabRestorerKey, this);
77  tab_restore_service_->LoadTabsFromLastSession();
78}
79
80void BrowserTabRestorer::TabRestoreServiceChanged(TabRestoreService* service) {
81}
82
83void BrowserTabRestorer::TabRestoreServiceDestroyed(
84    TabRestoreService* service) {
85}
86
87void BrowserTabRestorer::TabRestoreServiceLoaded(TabRestoreService* service) {
88  RestoreTab(browser_);
89  // This deletes us.
90  browser_->profile()->SetUserData(kBrowserTabRestorerKey, NULL);
91}
92
93void BrowserTabRestorer::OnBrowserRemoved(Browser* browser) {
94  // This deletes us.
95  browser_->profile()->SetUserData(kBrowserTabRestorerKey, NULL);
96}
97
98}  // namespace
99
100void RestoreTab(Browser* browser) {
101  content::RecordAction(base::UserMetricsAction("RestoreTab"));
102  TabRestoreService* service =
103      TabRestoreServiceFactory::GetForProfile(browser->profile());
104  if (!service)
105    return;
106
107  if (service->IsLoaded()) {
108    service->RestoreMostRecentEntry(browser->tab_restore_service_delegate(),
109                                    browser->host_desktop_type());
110    return;
111  }
112
113  BrowserTabRestorer::CreateIfNecessary(browser);
114}
115
116}  // namespace chrome
117