- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / ntp / recently_closed_tabs_handler.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/webui/ntp/recently_closed_tabs_handler.h"
6
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"
20
21 #if defined(OS_ANDROID)
22 #include "chrome/browser/sessions/session_restore.h"
23 #endif
24
25 namespace {
26
27 void TabToValue(const TabRestoreService::Tab& tab,
28                 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());
35 }
36
37 void WindowToValue(const TabRestoreService::Window& window,
38                    DictionaryValue* dictionary) {
39   DCHECK(!window.tabs.empty());
40
41   scoped_ptr<ListValue> tab_values(new ListValue());
42   for (size_t i = 0; i < window.tabs.size(); ++i) {
43     DictionaryValue* tab_value = new DictionaryValue();
44     TabToValue(window.tabs[i], tab_value);
45     tab_values->Append(tab_value);
46   }
47
48   dictionary->SetString("type", "window");
49   dictionary->SetDouble("timestamp", window.timestamp.ToDoubleT());
50   dictionary->Set("tabs", tab_values.release());
51 }
52
53 }  // namespace
54
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)));
65 }
66
67 RecentlyClosedTabsHandler::~RecentlyClosedTabsHandler() {
68   if (tab_restore_service_)
69     tab_restore_service_->RemoveObserver(this);
70 }
71
72 void RecentlyClosedTabsHandler::HandleReopenTab(const ListValue* args) {
73   if (!tab_restore_service_)
74     return;
75
76   double session_to_restore = 0.0;
77   CHECK(args->GetDouble(0, &session_to_restore));
78
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;
87
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;
92
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));
98
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);
102
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
119 }
120
121 void RecentlyClosedTabsHandler::HandleClearRecentlyClosed(
122     const ListValue* args) {
123   EnsureTabRestoreService();
124   if (tab_restore_service_)
125     tab_restore_service_->ClearEntries();
126 }
127
128 void RecentlyClosedTabsHandler::HandleGetRecentlyClosedTabs(
129     const ListValue* args) {
130   EnsureTabRestoreService();
131   if (tab_restore_service_)
132     TabRestoreServiceChanged(tab_restore_service_);
133 }
134
135 void RecentlyClosedTabsHandler::TabRestoreServiceChanged(
136     TabRestoreService* service) {
137   ListValue list_value;
138   TabRestoreService::Entries entries = service->entries();
139   CreateRecentlyClosedValues(entries, &list_value);
140
141   web_ui()->CallJavascriptFunction("ntp.setRecentlyClosedTabs", list_value);
142 }
143
144 void RecentlyClosedTabsHandler::TabRestoreServiceDestroyed(
145     TabRestoreService* service) {
146   tab_restore_service_ = NULL;
147 }
148
149 // static
150 void RecentlyClosedTabsHandler::CreateRecentlyClosedValues(
151     const TabRestoreService::Entries& entries, ListValue* entry_list_value) {
152   const int max_count = 10;
153   int added_count = 0;
154   // We filter the list of recently closed to only show 'interesting' entries,
155   // where an interesting entry is either a closed window or a closed tab
156   // whose selected navigation is not the new tab ui.
157   for (TabRestoreService::Entries::const_iterator it = entries.begin();
158        it != entries.end() && added_count < max_count; ++it) {
159     TabRestoreService::Entry* entry = *it;
160     scoped_ptr<DictionaryValue> entry_dict(new DictionaryValue());
161     if (entry->type == TabRestoreService::TAB) {
162       TabToValue(*static_cast<TabRestoreService::Tab*>(entry),
163                  entry_dict.get());
164     } else  {
165       DCHECK_EQ(entry->type, TabRestoreService::WINDOW);
166       WindowToValue(*static_cast<TabRestoreService::Window*>(entry),
167                     entry_dict.get());
168     }
169
170     entry_dict->SetInteger("sessionId", entry->id);
171     entry_list_value->Append(entry_dict.release());
172     ++added_count;
173   }
174 }
175
176 void RecentlyClosedTabsHandler::EnsureTabRestoreService() {
177   if (tab_restore_service_)
178     return;
179
180   tab_restore_service_ =
181       TabRestoreServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()));
182
183   // TabRestoreServiceFactory::GetForProfile() can return NULL (i.e., when in
184   // Off the Record mode)
185   if (tab_restore_service_) {
186     // This does nothing if the tabs have already been loaded or they
187     // shouldn't be loaded.
188     tab_restore_service_->LoadTabsFromLastSession();
189     tab_restore_service_->AddObserver(this);
190   }
191 }