Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / webui / ntp / recently_closed_tabs_handler.cc
bloba08fb9ac3a4d4c757c2faf058c77acd294c008ba
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/webui/ntp/recently_closed_tabs_handler.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/metrics/histogram.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/sessions/tab_restore_service_delegate.h"
12 #include "chrome/browser/sessions/tab_restore_service_factory.h"
13 #include "chrome/browser/ui/host_desktop.h"
14 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
15 #include "chrome/common/url_constants.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/browser/web_contents_view.h"
18 #include "content/public/browser/web_ui.h"
19 #include "ui/base/webui/web_ui_util.h"
21 #if defined(OS_ANDROID)
22 #include "chrome/browser/sessions/session_restore.h"
23 #endif
25 namespace {
27 void TabToValue(const TabRestoreService::Tab& tab,
28 base::DictionaryValue* dictionary) {
29 const sessions::SerializedNavigationEntry& current_navigation =
30 tab.navigations.at(tab.current_navigation_index);
31 NewTabUI::SetUrlTitleAndDirection(dictionary, current_navigation.title(),
32 current_navigation.virtual_url());
33 dictionary->SetString("type", "tab");
34 dictionary->SetDouble("timestamp", tab.timestamp.ToDoubleT());
37 void WindowToValue(const TabRestoreService::Window& window,
38 base::DictionaryValue* dictionary) {
39 DCHECK(!window.tabs.empty());
41 scoped_ptr<base::ListValue> tab_values(new base::ListValue());
42 for (size_t i = 0; i < window.tabs.size(); ++i) {
43 base::DictionaryValue* tab_value = new base::DictionaryValue();
44 TabToValue(window.tabs[i], tab_value);
45 tab_values->Append(tab_value);
48 dictionary->SetString("type", "window");
49 dictionary->SetDouble("timestamp", window.timestamp.ToDoubleT());
50 dictionary->Set("tabs", tab_values.release());
53 } // namespace
55 void RecentlyClosedTabsHandler::RegisterMessages() {
56 web_ui()->RegisterMessageCallback("getRecentlyClosedTabs",
57 base::Bind(&RecentlyClosedTabsHandler::HandleGetRecentlyClosedTabs,
58 base::Unretained(this)));
59 web_ui()->RegisterMessageCallback("reopenTab",
60 base::Bind(&RecentlyClosedTabsHandler::HandleReopenTab,
61 base::Unretained(this)));
62 web_ui()->RegisterMessageCallback("clearRecentlyClosed",
63 base::Bind(&RecentlyClosedTabsHandler::HandleClearRecentlyClosed,
64 base::Unretained(this)));
67 RecentlyClosedTabsHandler::~RecentlyClosedTabsHandler() {
68 if (tab_restore_service_)
69 tab_restore_service_->RemoveObserver(this);
72 void RecentlyClosedTabsHandler::HandleReopenTab(const base::ListValue* args) {
73 if (!tab_restore_service_)
74 return;
76 double session_to_restore = 0.0;
77 CHECK(args->GetDouble(0, &session_to_restore));
79 #if defined(OS_ANDROID)
80 // Find and remove the corresponding tab entry from TabRestoreService.
81 // We take ownership of the returned tab.
82 scoped_ptr<TabRestoreService::Tab> tab_entry(
83 tab_restore_service_->RemoveTabEntryById(static_cast<int>(
84 session_to_restore)));
85 if (tab_entry.get() == NULL)
86 return;
88 // RestoreForeignSessionTab needs a SessionTab.
89 SessionTab session_tab;
90 session_tab.current_navigation_index = tab_entry->current_navigation_index;
91 session_tab.navigations = tab_entry->navigations;
93 SessionRestore::RestoreForeignSessionTab(web_ui()->GetWebContents(),
94 session_tab, NEW_FOREGROUND_TAB);
95 #else
96 double index = -1.0;
97 CHECK(args->GetDouble(1, &index));
99 // There are actually less than 20 restore tab items displayed in the UI.
100 UMA_HISTOGRAM_ENUMERATION("NewTabPage.SessionRestore",
101 static_cast<int>(index), 20);
103 TabRestoreServiceDelegate* delegate =
104 TabRestoreServiceDelegate::FindDelegateForWebContents(
105 web_ui()->GetWebContents());
106 if (!delegate)
107 return;
108 chrome::HostDesktopType host_desktop_type =
109 chrome::GetHostDesktopTypeForNativeView(
110 web_ui()->GetWebContents()->GetView()->GetNativeView());
111 WindowOpenDisposition disposition = webui::GetDispositionFromClick(args, 2);
112 tab_restore_service_->RestoreEntryById(delegate,
113 static_cast<int>(session_to_restore),
114 host_desktop_type,
115 disposition);
116 // The current tab has been nuked at this point; don't touch any member
117 // variables.
118 #endif
121 void RecentlyClosedTabsHandler::HandleClearRecentlyClosed(
122 const base::ListValue* args) {
123 EnsureTabRestoreService();
124 if (tab_restore_service_)
125 tab_restore_service_->ClearEntries();
128 void RecentlyClosedTabsHandler::HandleGetRecentlyClosedTabs(
129 const base::ListValue* args) {
130 EnsureTabRestoreService();
131 if (tab_restore_service_)
132 TabRestoreServiceChanged(tab_restore_service_);
135 void RecentlyClosedTabsHandler::TabRestoreServiceChanged(
136 TabRestoreService* service) {
137 base::ListValue list_value;
138 TabRestoreService::Entries entries = service->entries();
139 CreateRecentlyClosedValues(entries, &list_value);
141 web_ui()->CallJavascriptFunction("ntp.setRecentlyClosedTabs", list_value);
144 void RecentlyClosedTabsHandler::TabRestoreServiceDestroyed(
145 TabRestoreService* service) {
146 tab_restore_service_ = NULL;
149 // static
150 void RecentlyClosedTabsHandler::CreateRecentlyClosedValues(
151 const TabRestoreService::Entries& entries,
152 base::ListValue* entry_list_value) {
153 const int max_count = 10;
154 int added_count = 0;
155 // We filter the list of recently closed to only show 'interesting' entries,
156 // where an interesting entry is either a closed window or a closed tab
157 // whose selected navigation is not the new tab ui.
158 for (TabRestoreService::Entries::const_iterator it = entries.begin();
159 it != entries.end() && added_count < max_count; ++it) {
160 TabRestoreService::Entry* entry = *it;
161 scoped_ptr<base::DictionaryValue> entry_dict(new base::DictionaryValue());
162 if (entry->type == TabRestoreService::TAB) {
163 TabToValue(*static_cast<TabRestoreService::Tab*>(entry),
164 entry_dict.get());
165 } else {
166 DCHECK_EQ(entry->type, TabRestoreService::WINDOW);
167 WindowToValue(*static_cast<TabRestoreService::Window*>(entry),
168 entry_dict.get());
171 entry_dict->SetInteger("sessionId", entry->id);
172 entry_list_value->Append(entry_dict.release());
173 ++added_count;
177 void RecentlyClosedTabsHandler::EnsureTabRestoreService() {
178 if (tab_restore_service_)
179 return;
181 tab_restore_service_ =
182 TabRestoreServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()));
184 // TabRestoreServiceFactory::GetForProfile() can return NULL (i.e., when in
185 // Off the Record mode)
186 if (tab_restore_service_) {
187 // This does nothing if the tabs have already been loaded or they
188 // shouldn't be loaded.
189 tab_restore_service_->LoadTabsFromLastSession();
190 tab_restore_service_->AddObserver(this);