Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: chrome/browser/ui/webui/ntp/foreign_session_handler.cc

Issue 11009013: NTP5: Starting implementation of a native menu for showing other device sessions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/webui/ntp/foreign_session_handler.h" 5 #include "chrome/browser/ui/webui/ntp/foreign_session_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/i18n/time_formatting.h" 12 #include "base/i18n/time_formatting.h"
13 #include "base/memory/scoped_vector.h" 13 #include "base/memory/scoped_vector.h"
14 #include "base/string_number_conversions.h" 14 #include "base/string_number_conversions.h"
15 #include "base/utf_string_conversions.h" 15 #include "base/utf_string_conversions.h"
16 #include "base/values.h" 16 #include "base/values.h"
17 #include "chrome/browser/prefs/pref_service.h" 17 #include "chrome/browser/prefs/pref_service.h"
18 #include "chrome/browser/prefs/scoped_user_pref_update.h" 18 #include "chrome/browser/prefs/scoped_user_pref_update.h"
19 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/sessions/session_restore.h" 20 #include "chrome/browser/sessions/session_restore.h"
21 #include "chrome/browser/sync/profile_sync_service.h" 21 #include "chrome/browser/sync/profile_sync_service.h"
22 #include "chrome/browser/sync/profile_sync_service_factory.h" 22 #include "chrome/browser/sync/profile_sync_service_factory.h"
23 #include "chrome/browser/ui/search/other_device_menu.h"
23 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" 24 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
24 #include "chrome/browser/ui/webui/session_favicon_source.h" 25 #include "chrome/browser/ui/webui/session_favicon_source.h"
25 #include "chrome/browser/ui/webui/web_ui_util.h" 26 #include "chrome/browser/ui/webui/web_ui_util.h"
26 #include "chrome/common/chrome_notification_types.h" 27 #include "chrome/common/chrome_notification_types.h"
27 #include "chrome/common/pref_names.h" 28 #include "chrome/common/pref_names.h"
28 #include "chrome/common/time_format.h" 29 #include "chrome/common/time_format.h"
29 #include "chrome/common/url_constants.h" 30 #include "chrome/common/url_constants.h"
30 #include "content/public/browser/notification_service.h" 31 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/notification_source.h" 32 #include "content/public/browser/notification_source.h"
32 #include "content/public/browser/web_ui.h"
33 #include "grit/generated_resources.h" 33 #include "grit/generated_resources.h"
34 #include "ui/base/l10n/l10n_util.h" 34 #include "ui/base/l10n/l10n_util.h"
35 35
36 namespace browser_sync { 36 namespace browser_sync {
37 37
38 // Maximum number of session we're going to display on the NTP 38 // Maximum number of sessions we're going to display on the NTP
39 static const size_t kMaxSessionsToShow = 10; 39 static const size_t kMaxSessionsToShow = 10;
40 40
41 // Invalid value, used to note that we don't have a tab or window number.
42 static const int kInvalidId = -1;
43
44 namespace { 41 namespace {
45 42
46 // Comparator function for use with std::sort that will sort sessions by 43 // Comparator function for use with std::sort that will sort sessions by
47 // descending modified_time (i.e., most recent first). 44 // descending modified_time (i.e., most recent first).
48 bool SortSessionsByRecency(const SyncedSession* s1, const SyncedSession* s2) { 45 bool SortSessionsByRecency(const SyncedSession* s1, const SyncedSession* s2) {
49 return s1->modified_time > s2->modified_time; 46 return s1->modified_time > s2->modified_time;
50 } 47 }
51 48
52 } // namepace 49 } // namepace
53 50
54 ForeignSessionHandler::ForeignSessionHandler() { 51 ForeignSessionHandler::ForeignSessionHandler() {
55 } 52 }
56 53
57 // static 54 // static
58 void ForeignSessionHandler::RegisterUserPrefs(PrefService* prefs) { 55 void ForeignSessionHandler::RegisterUserPrefs(PrefService* prefs) {
59 prefs->RegisterDictionaryPref(prefs::kNtpCollapsedForeignSessions, 56 prefs->RegisterDictionaryPref(prefs::kNtpCollapsedForeignSessions,
60 PrefService::UNSYNCABLE_PREF); 57 PrefService::UNSYNCABLE_PREF);
61 } 58 }
62 59
60 // static
61 void ForeignSessionHandler::OpenForeignSession(
62 content::WebUI* web_ui,
63 const std::string& session_string_value,
64 SessionID::id_type window_num,
65 SessionID::id_type tab_id,
66 const WindowOpenDisposition& disposition) {
67
68 SessionModelAssociator* associator = GetModelAssociator(web_ui);
69 if (!associator)
70 return;
71
72 if (tab_id != kInvalidId) {
73 // We don't actually care about |window_num|, this is just a sanity check.
74 DCHECK_LT(kInvalidId, window_num);
75 const SessionTab* tab;
76 if (!associator->GetForeignTab(session_string_value, tab_id, &tab)) {
77 LOG(ERROR) << "Failed to load foreign tab.";
78 return;
79 }
80 SessionRestore::RestoreForeignSessionTab(
81 web_ui->GetWebContents(), *tab, disposition);
82 } else {
83 std::vector<const SessionWindow*> windows;
84 // Note: we don't own the ForeignSessions themselves.
85 if (!associator->GetForeignSession(session_string_value, &windows)) {
86 LOG(ERROR) << "ForeignSessionHandler failed to get session data from"
87 "SessionModelAssociator.";
88 return;
89 }
90 std::vector<const SessionWindow*>::const_iterator iter_begin =
91 windows.begin() + ((window_num == kInvalidId) ? 0 : window_num);
92 std::vector<const SessionWindow*>::const_iterator iter_end =
93 ((window_num == kInvalidId) ?
94 std::vector<const SessionWindow*>::const_iterator(windows.end()) :
95 iter_begin + 1);
96 SessionRestore::RestoreForeignSessionWindows(
97 Profile::FromWebUI(web_ui), iter_begin, iter_end);
98 }
99 }
100
101 // static
102 bool ForeignSessionHandler::SessionTabToValue(
103 const SessionTab& tab,
104 DictionaryValue* dictionary) {
105 if (tab.navigations.empty())
106 return false;
107 int selected_index = tab.current_navigation_index;
108 selected_index = std::max(
109 0,
110 std::min(selected_index,
111 static_cast<int>(tab.navigations.size() - 1)));
112 const TabNavigation& current_navigation =
113 tab.navigations.at(selected_index);
114 GURL tab_url = current_navigation.virtual_url();
115 if (tab_url == GURL(chrome::kChromeUINewTabURL))
116 return false;
117 NewTabUI::SetUrlTitleAndDirection(dictionary, current_navigation.title(),
118 tab_url);
119 dictionary->SetString("type", "tab");
120 dictionary->SetDouble("timestamp",
121 static_cast<double>(tab.timestamp.ToInternalValue()));
122 // TODO(jeremycho): Rename to tabId?
123 dictionary->SetInteger("sessionId", tab.tab_id.id());
124 return true;
125 }
126
127 // static
128 SessionModelAssociator* ForeignSessionHandler::GetModelAssociator(
129 content::WebUI* web_ui) {
130 Profile* profile = Profile::FromWebUI(web_ui);
131 ProfileSyncService* service =
132 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
133
134 // Only return the associator if it exists and it is done syncing sessions.
135 if (service && service->ShouldPushChanges())
136 return service->GetSessionModelAssociator();
137
138 return NULL;
139 }
140
63 void ForeignSessionHandler::RegisterMessages() { 141 void ForeignSessionHandler::RegisterMessages() {
64 Init(); 142 Init();
65 web_ui()->RegisterMessageCallback("getForeignSessions", 143 web_ui()->RegisterMessageCallback("getForeignSessions",
66 base::Bind(&ForeignSessionHandler::HandleGetForeignSessions, 144 base::Bind(&ForeignSessionHandler::HandleGetForeignSessions,
67 base::Unretained(this))); 145 base::Unretained(this)));
68 web_ui()->RegisterMessageCallback("openForeignSession", 146 web_ui()->RegisterMessageCallback("openForeignSession",
69 base::Bind(&ForeignSessionHandler::HandleOpenForeignSession, 147 base::Bind(&ForeignSessionHandler::HandleOpenForeignSession,
70 base::Unretained(this))); 148 base::Unretained(this)));
71 web_ui()->RegisterMessageCallback("setForeignSessionCollapsed", 149 web_ui()->RegisterMessageCallback("setForeignSessionCollapsed",
72 base::Bind(&ForeignSessionHandler::HandleSetForeignSessionCollapsed, 150 base::Bind(&ForeignSessionHandler::HandleSetForeignSessionCollapsed,
73 base::Unretained(this))); 151 base::Unretained(this)));
152 web_ui()->RegisterMessageCallback("showOtherDevice",
153 base::Bind(&ForeignSessionHandler::HandleShowOtherDevice,
154 base::Unretained(this)));
74 } 155 }
75 156
76 void ForeignSessionHandler::Init() { 157 void ForeignSessionHandler::Init() {
77 Profile* profile = Profile::FromWebUI(web_ui()); 158 Profile* profile = Profile::FromWebUI(web_ui());
78 ProfileSyncService* service = 159 ProfileSyncService* service =
79 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); 160 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
80 registrar_.Add(this, chrome::NOTIFICATION_SYNC_CONFIGURE_DONE, 161 registrar_.Add(this, chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
81 content::Source<ProfileSyncService>(service)); 162 content::Source<ProfileSyncService>(service));
82 registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED, 163 registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED,
83 content::Source<Profile>(profile)); 164 content::Source<Profile>(profile));
(...skipping 19 matching lines...) Expand all
103 // Fall through. 184 // Fall through.
104 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE: 185 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE:
105 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED: 186 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED:
106 HandleGetForeignSessions(&list_value); 187 HandleGetForeignSessions(&list_value);
107 break; 188 break;
108 default: 189 default:
109 NOTREACHED(); 190 NOTREACHED();
110 } 191 }
111 } 192 }
112 193
113 SessionModelAssociator* ForeignSessionHandler::GetModelAssociator() {
114 Profile* profile = Profile::FromWebUI(web_ui());
115 ProfileSyncService* service =
116 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
117
118 // Only return the associator if it exists and it is done syncing sessions.
119 if (service && service->ShouldPushChanges())
120 return service->GetSessionModelAssociator();
121
122 return NULL;
123 }
124 194
125 bool ForeignSessionHandler::IsTabSyncEnabled() { 195 bool ForeignSessionHandler::IsTabSyncEnabled() {
126 Profile* profile = Profile::FromWebUI(web_ui()); 196 Profile* profile = Profile::FromWebUI(web_ui());
127 ProfileSyncService* service = 197 ProfileSyncService* service =
128 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); 198 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
129 return service && service->GetPreferredDataTypes().Has(syncer::SESSIONS); 199 return service && service->GetPreferredDataTypes().Has(syncer::SESSIONS);
130 } 200 }
131 201
132 string16 ForeignSessionHandler::FormatSessionTime(const base::Time& time) { 202 string16 ForeignSessionHandler::FormatSessionTime(const base::Time& time) {
133 // Return a time like "1 hour ago", "2 days ago", etc. 203 // Return a time like "1 hour ago", "2 days ago", etc.
134 return TimeFormat::TimeElapsed(base::Time::Now() - time); 204 return TimeFormat::TimeElapsed(base::Time::Now() - time);
135 } 205 }
136 206
137 void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) { 207 void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) {
138 SessionModelAssociator* associator = GetModelAssociator(); 208 SessionModelAssociator* associator = GetModelAssociator(web_ui());
139 std::vector<const SyncedSession*> sessions; 209 std::vector<const SyncedSession*> sessions;
140 210
141 ListValue session_list; 211 ListValue session_list;
142 if (associator && associator->GetAllForeignSessions(&sessions)) { 212 if (associator && associator->GetAllForeignSessions(&sessions)) {
143 // Sort sessions from most recent to least recent. 213 // Sort sessions from most recent to least recent.
144 std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency); 214 std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency);
145 215
146 // Use a pref to keep track of sessions that were collapsed by the user. 216 // Use a pref to keep track of sessions that were collapsed by the user.
147 // To prevent the pref from accumulating stale sessions, clear it each time 217 // To prevent the pref from accumulating stale sessions, clear it each time
148 // and only add back sessions that are still current. 218 // and only add back sessions that are still current.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 289
220 // Extract tab id. 290 // Extract tab id.
221 std::string tab_id_str; 291 std::string tab_id_str;
222 SessionID::id_type tab_id = kInvalidId; 292 SessionID::id_type tab_id = kInvalidId;
223 if (num_args >= 3 && (!args->GetString(2, &tab_id_str) || 293 if (num_args >= 3 && (!args->GetString(2, &tab_id_str) ||
224 !base::StringToInt(tab_id_str, &tab_id))) { 294 !base::StringToInt(tab_id_str, &tab_id))) {
225 LOG(ERROR) << "Failed to extract tab SessionID."; 295 LOG(ERROR) << "Failed to extract tab SessionID.";
226 return; 296 return;
227 } 297 }
228 298
229 SessionModelAssociator* associator = GetModelAssociator(); 299 WindowOpenDisposition disposition =
230 if (!associator) 300 web_ui_util::GetDispositionFromClick(args, 3);
231 return;
232 301
233 if (tab_id != kInvalidId) { 302 OpenForeignSession(
234 // We don't actually care about |window_num|, this is just a sanity check. 303 web_ui(), session_string_value, window_num, tab_id, disposition);
235 DCHECK_LT(kInvalidId, window_num);
236 const SessionTab* tab;
237 if (!associator->GetForeignTab(session_string_value, tab_id, &tab)) {
238 LOG(ERROR) << "Failed to load foreign tab.";
239 return;
240 }
241 WindowOpenDisposition disposition =
242 web_ui_util::GetDispositionFromClick(args, 3);
243 SessionRestore::RestoreForeignSessionTab(
244 web_ui()->GetWebContents(), *tab, disposition);
245 } else {
246 std::vector<const SessionWindow*> windows;
247 // Note: we don't own the ForeignSessions themselves.
248 if (!associator->GetForeignSession(session_string_value, &windows)) {
249 LOG(ERROR) << "ForeignSessionHandler failed to get session data from"
250 "SessionModelAssociator.";
251 return;
252 }
253 std::vector<const SessionWindow*>::const_iterator iter_begin =
254 windows.begin() + ((window_num == kInvalidId) ? 0 : window_num);
255 std::vector<const SessionWindow*>::const_iterator iter_end =
256 ((window_num == kInvalidId) ?
257 std::vector<const SessionWindow*>::const_iterator(windows.end()) :
258 iter_begin + 1);
259 SessionRestore::RestoreForeignSessionWindows(
260 Profile::FromWebUI(web_ui()), iter_begin, iter_end);
261 }
262 } 304 }
263 305
264 void ForeignSessionHandler::HandleSetForeignSessionCollapsed( 306 void ForeignSessionHandler::HandleSetForeignSessionCollapsed(
265 const ListValue* args) { 307 const ListValue* args) {
266 if (args->GetSize() != 2U) { 308 if (args->GetSize() != 2U) {
267 LOG(ERROR) << "Wrong number of args to setForeignSessionCollapsed"; 309 LOG(ERROR) << "Wrong number of args to setForeignSessionCollapsed";
268 return; 310 return;
269 } 311 }
270 312
271 // Get the session tag argument (required). 313 // Get the session tag argument (required).
(...skipping 12 matching lines...) Expand all
284 // Store session tags for collapsed sessions in a preference so that the 326 // Store session tags for collapsed sessions in a preference so that the
285 // collapsed state persists. 327 // collapsed state persists.
286 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 328 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
287 DictionaryPrefUpdate update(prefs, prefs::kNtpCollapsedForeignSessions); 329 DictionaryPrefUpdate update(prefs, prefs::kNtpCollapsedForeignSessions);
288 if (is_collapsed) 330 if (is_collapsed)
289 update.Get()->SetBoolean(session_tag, true); 331 update.Get()->SetBoolean(session_tag, true);
290 else 332 else
291 update.Get()->Remove(session_tag, NULL); 333 update.Get()->Remove(session_tag, NULL);
292 } 334 }
293 335
294 bool ForeignSessionHandler::SessionTabToValue( 336 // TODO(jeremycho): Do not submit. Just for testing. Use
295 const SessionTab& tab, 337 // http://codereview.chromium.org/11003002/ once it's submitted.
296 DictionaryValue* dictionary) { 338 void ForeignSessionHandler::HandleShowOtherDevice(const ListValue* args) {
297 if (tab.navigations.empty()) 339 // Extract horizontal coordinate of the click within the application's client
298 return false; 340 // area.
299 int selected_index = tab.current_navigation_index; 341 double client_x;
300 selected_index = std::max( 342 if (!args->GetDouble(0, &client_x)) {
301 0, 343 LOG(ERROR) << "Failed to extract X coordinate.";
302 std::min(selected_index, 344 return;
303 static_cast<int>(tab.navigations.size() - 1))); 345 }
304 const TabNavigation& current_navigation = 346
305 tab.navigations.at(selected_index); 347 // Extract vertical coordinate of the click within the application's client
306 GURL tab_url = current_navigation.virtual_url(); 348 // area.
307 if (tab_url == GURL(chrome::kChromeUINewTabURL)) 349 double client_y;
308 return false; 350 if (!args->GetDouble(1, &client_y)) {
309 NewTabUI::SetUrlTitleAndDirection(dictionary, current_navigation.title(), 351 LOG(ERROR) << "Failed to extract Y coordinate.";
310 tab_url); 352 return;
311 dictionary->SetString("type", "tab"); 353 }
312 dictionary->SetDouble("timestamp", 354
313 static_cast<double>(tab.timestamp.ToInternalValue())); 355 SessionModelAssociator* associator = GetModelAssociator(web_ui());
314 dictionary->SetInteger("sessionId", tab.tab_id.id()); 356 std::vector<const SyncedSession*> sessions;
315 return true; 357
358 if (associator && associator->GetAllForeignSessions(&sessions)) {
359 // For testing only, show the most recent device session.
360 std::string session_string_value = sessions[0]->session_tag;
361 OtherDeviceMenu* menu = new OtherDeviceMenu(
362 web_ui(),
363 session_string_value, gfx::Point(client_x, client_y));
364 menu->ShowMenu();
365 }
316 } 366 }
317 367
318 bool ForeignSessionHandler::SessionWindowToValue( 368 bool ForeignSessionHandler::SessionWindowToValue(
319 const SessionWindow& window, 369 const SessionWindow& window,
320 DictionaryValue* dictionary) { 370 DictionaryValue* dictionary) {
321 if (window.tabs.empty()) { 371 if (window.tabs.empty()) {
322 NOTREACHED(); 372 NOTREACHED();
323 return false; 373 return false;
324 } 374 }
325 scoped_ptr<ListValue> tab_values(new ListValue()); 375 scoped_ptr<ListValue> tab_values(new ListValue());
(...skipping 17 matching lines...) Expand all
343 dictionary->SetString("userVisibleTimestamp", 393 dictionary->SetString("userVisibleTimestamp",
344 last_synced < base::TimeDelta::FromMinutes(1) ? 394 last_synced < base::TimeDelta::FromMinutes(1) ?
345 l10n_util::GetStringUTF16(IDS_SYNC_TIME_JUST_NOW) : 395 l10n_util::GetStringUTF16(IDS_SYNC_TIME_JUST_NOW) :
346 TimeFormat::TimeElapsed(last_synced)); 396 TimeFormat::TimeElapsed(last_synced));
347 dictionary->SetInteger("sessionId", window.window_id.id()); 397 dictionary->SetInteger("sessionId", window.window_id.id());
348 dictionary->Set("tabs", tab_values.release()); 398 dictionary->Set("tabs", tab_values.release());
349 return true; 399 return true;
350 } 400 }
351 401
352 } // namespace browser_sync 402 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698