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

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: Fix dumb typo. Created 8 years, 1 month 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
24 #if !defined(OS_ANDROID)
25 #include "chrome/browser/ui/search/other_device_menu_controller.h"
26 #endif
27
23 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" 28 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
24 #include "chrome/browser/ui/webui/session_favicon_source.h" 29 #include "chrome/browser/ui/webui/session_favicon_source.h"
25 #include "chrome/browser/ui/webui/web_ui_util.h" 30 #include "chrome/browser/ui/webui/web_ui_util.h"
26 #include "chrome/common/chrome_notification_types.h" 31 #include "chrome/common/chrome_notification_types.h"
27 #include "chrome/common/pref_names.h" 32 #include "chrome/common/pref_names.h"
28 #include "chrome/common/time_format.h" 33 #include "chrome/common/time_format.h"
29 #include "chrome/common/url_constants.h" 34 #include "chrome/common/url_constants.h"
30 #include "content/public/browser/notification_service.h" 35 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/notification_source.h" 36 #include "content/public/browser/notification_source.h"
32 #include "content/public/browser/web_ui.h"
33 #include "grit/generated_resources.h" 37 #include "grit/generated_resources.h"
34 #include "ui/base/l10n/l10n_util.h" 38 #include "ui/base/l10n/l10n_util.h"
35 39
36 namespace browser_sync { 40 namespace browser_sync {
37 41
38 // Maximum number of session we're going to display on the NTP 42 // Maximum number of sessions we're going to display on the NTP
39 static const size_t kMaxSessionsToShow = 10; 43 static const size_t kMaxSessionsToShow = 10;
40 44
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 { 45 namespace {
45 46
46 // Comparator function for use with std::sort that will sort sessions by 47 // Comparator function for use with std::sort that will sort sessions by
47 // descending modified_time (i.e., most recent first). 48 // descending modified_time (i.e., most recent first).
48 bool SortSessionsByRecency(const SyncedSession* s1, const SyncedSession* s2) { 49 bool SortSessionsByRecency(const SyncedSession* s1, const SyncedSession* s2) {
49 return s1->modified_time > s2->modified_time; 50 return s1->modified_time > s2->modified_time;
50 } 51 }
51 52
52 } // namepace 53 } // namepace
53 54
54 ForeignSessionHandler::ForeignSessionHandler() { 55 ForeignSessionHandler::ForeignSessionHandler() {
55 } 56 }
56 57
57 // static 58 // static
58 void ForeignSessionHandler::RegisterUserPrefs(PrefService* prefs) { 59 void ForeignSessionHandler::RegisterUserPrefs(PrefService* prefs) {
59 prefs->RegisterDictionaryPref(prefs::kNtpCollapsedForeignSessions, 60 prefs->RegisterDictionaryPref(prefs::kNtpCollapsedForeignSessions,
60 PrefService::UNSYNCABLE_PREF); 61 PrefService::UNSYNCABLE_PREF);
61 } 62 }
62 63
64 // static
65 void ForeignSessionHandler::OpenForeignSession(
66 content::WebUI* web_ui,
67 const std::string& session_string_value,
68 SessionID::id_type window_num,
69 SessionID::id_type tab_id,
70 const WindowOpenDisposition& disposition) {
71
72 SessionModelAssociator* associator = GetModelAssociator(web_ui);
73 if (!associator)
74 return;
75
76 if (tab_id != kInvalidId) {
77 // We don't actually care about |window_num|, this is just a sanity check.
78 DCHECK_LT(kInvalidId, window_num);
79 const SessionTab* tab;
80 if (!associator->GetForeignTab(session_string_value, tab_id, &tab)) {
81 LOG(ERROR) << "Failed to load foreign tab.";
82 return;
83 }
84 if (tab->navigations.empty()) {
85 LOG(ERROR) << "Foreign tab no longer has valid navigations.";
86 return;
87 }
88 SessionRestore::RestoreForeignSessionTab(
89 web_ui->GetWebContents(), *tab, disposition);
90 return;
91 }
92
93 std::vector<const SessionWindow*> windows;
94 // Note: we don't own the ForeignSessions themselves.
95 if (!associator->GetForeignSession(session_string_value, &windows)) {
96 LOG(ERROR) << "ForeignSessionHandler failed to get session data from"
97 "SessionModelAssociator.";
98 return;
99 }
100 std::vector<const SessionWindow*>::const_iterator iter_begin =
101 windows.begin() + (window_num == kInvalidId ? 0 : window_num);
102 std::vector<const SessionWindow*>::const_iterator iter_end =
103 window_num == kInvalidId ?
104 std::vector<const SessionWindow*>::const_iterator(windows.end()) :
105 iter_begin + 1;
106 SessionRestore::RestoreForeignSessionWindows(
107 Profile::FromWebUI(web_ui), iter_begin, iter_end);
108 }
109
110 // static
111 bool ForeignSessionHandler::SessionTabToValue(
112 const SessionTab& tab,
113 DictionaryValue* dictionary) {
114 if (tab.navigations.empty())
115 return false;
116
117 int selected_index = std::min(tab.current_navigation_index,
118 static_cast<int>(tab.navigations.size() - 1));
119 const TabNavigation& current_navigation =
120 tab.navigations.at(selected_index);
121 GURL tab_url = current_navigation.virtual_url();
122 if (tab_url == GURL(chrome::kChromeUINewTabURL))
123 return false;
124
125 NewTabUI::SetUrlTitleAndDirection(dictionary, current_navigation.title(),
126 tab_url);
127 dictionary->SetString("type", "tab");
128 dictionary->SetDouble("timestamp",
129 static_cast<double>(tab.timestamp.ToInternalValue()));
130 // TODO(jeremycho): This should probably be renamed to tabId to avoid
131 // confusion with the ID corresponding to a session. Investigate all the
132 // places (C++ and JS) where this is being used. (http://crbug.com/154865).
133 dictionary->SetInteger("sessionId", tab.tab_id.id());
134 return true;
135 }
136
137 // static
138 SessionModelAssociator* ForeignSessionHandler::GetModelAssociator(
139 content::WebUI* web_ui) {
140 Profile* profile = Profile::FromWebUI(web_ui);
141 ProfileSyncService* service =
142 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
143
144 // Only return the associator if it exists and it is done syncing sessions.
145 if (service && service->ShouldPushChanges())
146 return service->GetSessionModelAssociator();
147
148 return NULL;
149 }
150
63 void ForeignSessionHandler::RegisterMessages() { 151 void ForeignSessionHandler::RegisterMessages() {
64 Init(); 152 Init();
65 web_ui()->RegisterMessageCallback("getForeignSessions", 153 web_ui()->RegisterMessageCallback("getForeignSessions",
66 base::Bind(&ForeignSessionHandler::HandleGetForeignSessions, 154 base::Bind(&ForeignSessionHandler::HandleGetForeignSessions,
67 base::Unretained(this))); 155 base::Unretained(this)));
68 web_ui()->RegisterMessageCallback("openForeignSession", 156 web_ui()->RegisterMessageCallback("openForeignSession",
69 base::Bind(&ForeignSessionHandler::HandleOpenForeignSession, 157 base::Bind(&ForeignSessionHandler::HandleOpenForeignSession,
70 base::Unretained(this))); 158 base::Unretained(this)));
71 web_ui()->RegisterMessageCallback("setForeignSessionCollapsed", 159 web_ui()->RegisterMessageCallback("setForeignSessionCollapsed",
72 base::Bind(&ForeignSessionHandler::HandleSetForeignSessionCollapsed, 160 base::Bind(&ForeignSessionHandler::HandleSetForeignSessionCollapsed,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 // Fall through. 194 // Fall through.
107 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE: 195 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE:
108 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED: 196 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED:
109 HandleGetForeignSessions(&list_value); 197 HandleGetForeignSessions(&list_value);
110 break; 198 break;
111 default: 199 default:
112 NOTREACHED(); 200 NOTREACHED();
113 } 201 }
114 } 202 }
115 203
116 SessionModelAssociator* ForeignSessionHandler::GetModelAssociator() {
117 Profile* profile = Profile::FromWebUI(web_ui());
118 ProfileSyncService* service =
119 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
120
121 // Only return the associator if it exists and it is done syncing sessions.
122 if (service && service->ShouldPushChanges())
123 return service->GetSessionModelAssociator();
124
125 return NULL;
126 }
127 204
128 bool ForeignSessionHandler::IsTabSyncEnabled() { 205 bool ForeignSessionHandler::IsTabSyncEnabled() {
129 Profile* profile = Profile::FromWebUI(web_ui()); 206 Profile* profile = Profile::FromWebUI(web_ui());
130 ProfileSyncService* service = 207 ProfileSyncService* service =
131 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); 208 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
132 return service && service->GetPreferredDataTypes().Has(syncer::SESSIONS); 209 return service && service->GetPreferredDataTypes().Has(syncer::SESSIONS);
133 } 210 }
134 211
135 string16 ForeignSessionHandler::FormatSessionTime(const base::Time& time) { 212 string16 ForeignSessionHandler::FormatSessionTime(const base::Time& time) {
136 // Return a time like "1 hour ago", "2 days ago", etc. 213 // Return a time like "1 hour ago", "2 days ago", etc.
137 return TimeFormat::TimeElapsed(base::Time::Now() - time); 214 return TimeFormat::TimeElapsed(base::Time::Now() - time);
138 } 215 }
139 216
140 void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) { 217 void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) {
141 SessionModelAssociator* associator = GetModelAssociator(); 218 SessionModelAssociator* associator = GetModelAssociator(web_ui());
142 std::vector<const SyncedSession*> sessions; 219 std::vector<const SyncedSession*> sessions;
143 220
144 ListValue session_list; 221 ListValue session_list;
145 if (associator && associator->GetAllForeignSessions(&sessions)) { 222 if (associator && associator->GetAllForeignSessions(&sessions)) {
146 // Sort sessions from most recent to least recent. 223 // Sort sessions from most recent to least recent.
147 std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency); 224 std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency);
148 225
149 // Use a pref to keep track of sessions that were collapsed by the user. 226 // Use a pref to keep track of sessions that were collapsed by the user.
150 // To prevent the pref from accumulating stale sessions, clear it each time 227 // To prevent the pref from accumulating stale sessions, clear it each time
151 // and only add back sessions that are still current. 228 // and only add back sessions that are still current.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 299
223 // Extract tab id. 300 // Extract tab id.
224 std::string tab_id_str; 301 std::string tab_id_str;
225 SessionID::id_type tab_id = kInvalidId; 302 SessionID::id_type tab_id = kInvalidId;
226 if (num_args >= 3 && (!args->GetString(2, &tab_id_str) || 303 if (num_args >= 3 && (!args->GetString(2, &tab_id_str) ||
227 !base::StringToInt(tab_id_str, &tab_id))) { 304 !base::StringToInt(tab_id_str, &tab_id))) {
228 LOG(ERROR) << "Failed to extract tab SessionID."; 305 LOG(ERROR) << "Failed to extract tab SessionID.";
229 return; 306 return;
230 } 307 }
231 308
232 SessionModelAssociator* associator = GetModelAssociator(); 309 WindowOpenDisposition disposition =
233 if (!associator) 310 web_ui_util::GetDispositionFromClick(args, 3);
234 return;
235 311
236 if (tab_id != kInvalidId) { 312 OpenForeignSession(
237 // We don't actually care about |window_num|, this is just a sanity check. 313 web_ui(), session_string_value, window_num, tab_id, disposition);
238 DCHECK_LT(kInvalidId, window_num);
239 const SessionTab* tab;
240 if (!associator->GetForeignTab(session_string_value, tab_id, &tab)) {
241 LOG(ERROR) << "Failed to load foreign tab.";
242 return;
243 }
244 if (tab->navigations.size() == 0) {
245 LOG(ERROR) << "Foreign tab no longer has valid navigations.";
246 return;
247 }
248 WindowOpenDisposition disposition =
249 web_ui_util::GetDispositionFromClick(args, 3);
250 SessionRestore::RestoreForeignSessionTab(
251 web_ui()->GetWebContents(), *tab, disposition);
252 } else {
253 std::vector<const SessionWindow*> windows;
254 // Note: we don't own the ForeignSessions themselves.
255 if (!associator->GetForeignSession(session_string_value, &windows)) {
256 LOG(ERROR) << "ForeignSessionHandler failed to get session data from"
257 "SessionModelAssociator.";
258 return;
259 }
260 std::vector<const SessionWindow*>::const_iterator iter_begin =
261 windows.begin() + ((window_num == kInvalidId) ? 0 : window_num);
262 std::vector<const SessionWindow*>::const_iterator iter_end =
263 ((window_num == kInvalidId) ?
264 std::vector<const SessionWindow*>::const_iterator(windows.end()) :
265 iter_begin + 1);
266 SessionRestore::RestoreForeignSessionWindows(
267 Profile::FromWebUI(web_ui()), iter_begin, iter_end);
268 }
269 } 314 }
270 315
271 void ForeignSessionHandler::HandleSetForeignSessionCollapsed( 316 void ForeignSessionHandler::HandleSetForeignSessionCollapsed(
272 const ListValue* args) { 317 const ListValue* args) {
273 if (args->GetSize() != 2U) { 318 if (args->GetSize() != 2U) {
274 LOG(ERROR) << "Wrong number of args to setForeignSessionCollapsed"; 319 LOG(ERROR) << "Wrong number of args to setForeignSessionCollapsed";
275 return; 320 return;
276 } 321 }
277 322
278 // Get the session tag argument (required). 323 // Get the session tag argument (required).
(...skipping 14 matching lines...) Expand all
293 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 338 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
294 DictionaryPrefUpdate update(prefs, prefs::kNtpCollapsedForeignSessions); 339 DictionaryPrefUpdate update(prefs, prefs::kNtpCollapsedForeignSessions);
295 if (is_collapsed) 340 if (is_collapsed)
296 update.Get()->SetBoolean(session_tag, true); 341 update.Get()->SetBoolean(session_tag, true);
297 else 342 else
298 update.Get()->Remove(session_tag, NULL); 343 update.Get()->Remove(session_tag, NULL);
299 } 344 }
300 345
301 void ForeignSessionHandler::HandleShowOtherDeviceSessionPopup( 346 void ForeignSessionHandler::HandleShowOtherDeviceSessionPopup(
302 const ListValue* args) { 347 const ListValue* args) {
348 // Exclude Android until an OtherDeviceMenu view is implemented for it.
349 #if !defined(OS_ANDROID)
303 CHECK(args->GetSize() == 3U); 350 CHECK(args->GetSize() == 3U);
304 351
305 // Extract the session tag. 352 // Extract the session tag.
306 std::string session_string_value; 353 std::string session_string_value;
307 CHECK(args->GetString(0, &session_string_value)); 354 CHECK(args->GetString(0, &session_string_value));
308 355
309 // Extract horizontal coordinate of the click within the application's client 356 // Extract horizontal coordinate of the click relative to the origin of the
310 // area. 357 // screen coordinate system.
311 double client_x; 358 double screen_x;
312 CHECK(args->GetDouble(1, &client_x)); 359 CHECK(args->GetDouble(1, &screen_x));
313 360
314 // Extract vertical coordinate of the click within the application's client 361 // Extract vertical coordinate of the click relative to the origin of the
315 // area. 362 // screen coordinate system.
316 double client_y; 363 double screen_y;
317 CHECK(args->GetDouble(2, &client_y)); 364 CHECK(args->GetDouble(2, &screen_y));
318 365 OtherDeviceMenuController* menu = new OtherDeviceMenuController(
319 // TODO(vadimt): implement this method. 366 web_ui(),
320 } 367 session_string_value, gfx::Point(screen_x, screen_y));
321 368 menu->ShowMenu();
322 bool ForeignSessionHandler::SessionTabToValue( 369 #endif
323 const SessionTab& tab,
324 DictionaryValue* dictionary) {
325 if (tab.navigations.empty())
326 return false;
327 int selected_index = tab.current_navigation_index;
328 selected_index = std::max(
329 0,
330 std::min(selected_index,
331 static_cast<int>(tab.navigations.size() - 1)));
332 const TabNavigation& current_navigation =
333 tab.navigations.at(selected_index);
334 GURL tab_url = current_navigation.virtual_url();
335 if (tab_url == GURL(chrome::kChromeUINewTabURL))
336 return false;
337 NewTabUI::SetUrlTitleAndDirection(dictionary, current_navigation.title(),
338 tab_url);
339 dictionary->SetString("type", "tab");
340 dictionary->SetDouble("timestamp",
341 static_cast<double>(tab.timestamp.ToInternalValue()));
342 dictionary->SetInteger("sessionId", tab.tab_id.id());
343 return true;
344 } 370 }
345 371
346 bool ForeignSessionHandler::SessionWindowToValue( 372 bool ForeignSessionHandler::SessionWindowToValue(
347 const SessionWindow& window, 373 const SessionWindow& window,
348 DictionaryValue* dictionary) { 374 DictionaryValue* dictionary) {
349 if (window.tabs.empty()) { 375 if (window.tabs.empty()) {
350 NOTREACHED(); 376 NOTREACHED();
351 return false; 377 return false;
352 } 378 }
353 scoped_ptr<ListValue> tab_values(new ListValue()); 379 scoped_ptr<ListValue> tab_values(new ListValue());
(...skipping 17 matching lines...) Expand all
371 dictionary->SetString("userVisibleTimestamp", 397 dictionary->SetString("userVisibleTimestamp",
372 last_synced < base::TimeDelta::FromMinutes(1) ? 398 last_synced < base::TimeDelta::FromMinutes(1) ?
373 l10n_util::GetStringUTF16(IDS_SYNC_TIME_JUST_NOW) : 399 l10n_util::GetStringUTF16(IDS_SYNC_TIME_JUST_NOW) :
374 TimeFormat::TimeElapsed(last_synced)); 400 TimeFormat::TimeElapsed(last_synced));
375 dictionary->SetInteger("sessionId", window.window_id.id()); 401 dictionary->SetInteger("sessionId", window.window_id.id());
376 dictionary->Set("tabs", tab_values.release()); 402 dictionary->Set("tabs", tab_values.release());
377 return true; 403 return true;
378 } 404 }
379 405
380 } // namespace browser_sync 406 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698