OLD | NEW |
---|---|
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_controller.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 if (tab->navigations.empty()) { | |
81 LOG(ERROR) << "Foreign tab no longer has valid navigations."; | |
82 return; | |
83 } | |
84 SessionRestore::RestoreForeignSessionTab( | |
85 web_ui->GetWebContents(), *tab, disposition); | |
86 return; | |
87 } | |
88 | |
89 std::vector<const SessionWindow*> windows; | |
90 // Note: we don't own the ForeignSessions themselves. | |
91 if (!associator->GetForeignSession(session_string_value, &windows)) { | |
92 LOG(ERROR) << "ForeignSessionHandler failed to get session data from" | |
93 "SessionModelAssociator."; | |
94 return; | |
95 } | |
96 std::vector<const SessionWindow*>::const_iterator iter_begin = | |
97 windows.begin() + (window_num == kInvalidId ? 0 : window_num); | |
98 std::vector<const SessionWindow*>::const_iterator iter_end = | |
99 window_num == kInvalidId ? | |
100 std::vector<const SessionWindow*>::const_iterator(windows.end()) : | |
101 iter_begin + 1; | |
102 SessionRestore::RestoreForeignSessionWindows( | |
103 Profile::FromWebUI(web_ui), iter_begin, iter_end); | |
104 } | |
105 | |
106 // static | |
107 bool ForeignSessionHandler::SessionTabToValue( | |
108 const SessionTab& tab, | |
109 DictionaryValue* dictionary) { | |
110 if (tab.navigations.empty()) | |
111 return false; | |
112 | |
113 int selected_index = std::min(tab.current_navigation_index, | |
114 static_cast<int>(tab.navigations.size() - 1)); | |
115 const TabNavigation& current_navigation = | |
116 tab.navigations.at(selected_index); | |
117 GURL tab_url = current_navigation.virtual_url(); | |
118 if (tab_url == GURL(chrome::kChromeUINewTabURL)) | |
119 return false; | |
120 | |
121 NewTabUI::SetUrlTitleAndDirection(dictionary, current_navigation.title(), | |
122 tab_url); | |
123 dictionary->SetString("type", "tab"); | |
124 dictionary->SetDouble("timestamp", | |
125 static_cast<double>(tab.timestamp.ToInternalValue())); | |
126 // TODO(jeremycho): This should probably be renamed to tabId to avoid | |
127 // confusion with the ID corresponding to a session. Investigate all the | |
128 // places (C++ and JS) where this is being used. (http://crbug.com/154865). | |
129 dictionary->SetInteger("sessionId", tab.tab_id.id()); | |
130 return true; | |
131 } | |
132 | |
133 // static | |
134 SessionModelAssociator* ForeignSessionHandler::GetModelAssociator( | |
135 content::WebUI* web_ui) { | |
136 Profile* profile = Profile::FromWebUI(web_ui); | |
137 ProfileSyncService* service = | |
138 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); | |
139 | |
140 // Only return the associator if it exists and it is done syncing sessions. | |
141 if (service && service->ShouldPushChanges()) | |
142 return service->GetSessionModelAssociator(); | |
143 | |
144 return NULL; | |
145 } | |
146 | |
63 void ForeignSessionHandler::RegisterMessages() { | 147 void ForeignSessionHandler::RegisterMessages() { |
64 Init(); | 148 Init(); |
65 web_ui()->RegisterMessageCallback("getForeignSessions", | 149 web_ui()->RegisterMessageCallback("getForeignSessions", |
66 base::Bind(&ForeignSessionHandler::HandleGetForeignSessions, | 150 base::Bind(&ForeignSessionHandler::HandleGetForeignSessions, |
67 base::Unretained(this))); | 151 base::Unretained(this))); |
68 web_ui()->RegisterMessageCallback("openForeignSession", | 152 web_ui()->RegisterMessageCallback("openForeignSession", |
69 base::Bind(&ForeignSessionHandler::HandleOpenForeignSession, | 153 base::Bind(&ForeignSessionHandler::HandleOpenForeignSession, |
70 base::Unretained(this))); | 154 base::Unretained(this))); |
71 web_ui()->RegisterMessageCallback("setForeignSessionCollapsed", | 155 web_ui()->RegisterMessageCallback("setForeignSessionCollapsed", |
72 base::Bind(&ForeignSessionHandler::HandleSetForeignSessionCollapsed, | 156 base::Bind(&ForeignSessionHandler::HandleSetForeignSessionCollapsed, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 // Fall through. | 190 // Fall through. |
107 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE: | 191 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE: |
108 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED: | 192 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED: |
109 HandleGetForeignSessions(&list_value); | 193 HandleGetForeignSessions(&list_value); |
110 break; | 194 break; |
111 default: | 195 default: |
112 NOTREACHED(); | 196 NOTREACHED(); |
113 } | 197 } |
114 } | 198 } |
115 | 199 |
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 | 200 |
128 bool ForeignSessionHandler::IsTabSyncEnabled() { | 201 bool ForeignSessionHandler::IsTabSyncEnabled() { |
129 Profile* profile = Profile::FromWebUI(web_ui()); | 202 Profile* profile = Profile::FromWebUI(web_ui()); |
130 ProfileSyncService* service = | 203 ProfileSyncService* service = |
131 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); | 204 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); |
132 return service && service->GetPreferredDataTypes().Has(syncer::SESSIONS); | 205 return service && service->GetPreferredDataTypes().Has(syncer::SESSIONS); |
133 } | 206 } |
134 | 207 |
135 string16 ForeignSessionHandler::FormatSessionTime(const base::Time& time) { | 208 string16 ForeignSessionHandler::FormatSessionTime(const base::Time& time) { |
136 // Return a time like "1 hour ago", "2 days ago", etc. | 209 // Return a time like "1 hour ago", "2 days ago", etc. |
137 return TimeFormat::TimeElapsed(base::Time::Now() - time); | 210 return TimeFormat::TimeElapsed(base::Time::Now() - time); |
138 } | 211 } |
139 | 212 |
140 void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) { | 213 void ForeignSessionHandler::HandleGetForeignSessions(const ListValue* args) { |
141 SessionModelAssociator* associator = GetModelAssociator(); | 214 SessionModelAssociator* associator = GetModelAssociator(web_ui()); |
142 std::vector<const SyncedSession*> sessions; | 215 std::vector<const SyncedSession*> sessions; |
143 | 216 |
144 ListValue session_list; | 217 ListValue session_list; |
145 if (associator && associator->GetAllForeignSessions(&sessions)) { | 218 if (associator && associator->GetAllForeignSessions(&sessions)) { |
146 // Sort sessions from most recent to least recent. | 219 // Sort sessions from most recent to least recent. |
147 std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency); | 220 std::sort(sessions.begin(), sessions.end(), SortSessionsByRecency); |
148 | 221 |
149 // Use a pref to keep track of sessions that were collapsed by the user. | 222 // 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 | 223 // To prevent the pref from accumulating stale sessions, clear it each time |
151 // and only add back sessions that are still current. | 224 // and only add back sessions that are still current. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
222 | 295 |
223 // Extract tab id. | 296 // Extract tab id. |
224 std::string tab_id_str; | 297 std::string tab_id_str; |
225 SessionID::id_type tab_id = kInvalidId; | 298 SessionID::id_type tab_id = kInvalidId; |
226 if (num_args >= 3 && (!args->GetString(2, &tab_id_str) || | 299 if (num_args >= 3 && (!args->GetString(2, &tab_id_str) || |
227 !base::StringToInt(tab_id_str, &tab_id))) { | 300 !base::StringToInt(tab_id_str, &tab_id))) { |
228 LOG(ERROR) << "Failed to extract tab SessionID."; | 301 LOG(ERROR) << "Failed to extract tab SessionID."; |
229 return; | 302 return; |
230 } | 303 } |
231 | 304 |
232 SessionModelAssociator* associator = GetModelAssociator(); | 305 WindowOpenDisposition disposition = |
233 if (!associator) | 306 web_ui_util::GetDispositionFromClick(args, 3); |
234 return; | |
235 | 307 |
236 if (tab_id != kInvalidId) { | 308 OpenForeignSession( |
237 // We don't actually care about |window_num|, this is just a sanity check. | 309 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 } | 310 } |
270 | 311 |
271 void ForeignSessionHandler::HandleSetForeignSessionCollapsed( | 312 void ForeignSessionHandler::HandleSetForeignSessionCollapsed( |
272 const ListValue* args) { | 313 const ListValue* args) { |
273 if (args->GetSize() != 2U) { | 314 if (args->GetSize() != 2U) { |
274 LOG(ERROR) << "Wrong number of args to setForeignSessionCollapsed"; | 315 LOG(ERROR) << "Wrong number of args to setForeignSessionCollapsed"; |
275 return; | 316 return; |
276 } | 317 } |
277 | 318 |
278 // Get the session tag argument (required). | 319 // Get the session tag argument (required). |
(...skipping 20 matching lines...) Expand all Loading... | |
299 } | 340 } |
300 | 341 |
301 void ForeignSessionHandler::HandleShowOtherDeviceSessionPopup( | 342 void ForeignSessionHandler::HandleShowOtherDeviceSessionPopup( |
302 const ListValue* args) { | 343 const ListValue* args) { |
303 CHECK(args->GetSize() == 3U); | 344 CHECK(args->GetSize() == 3U); |
304 | 345 |
305 // Extract the session tag. | 346 // Extract the session tag. |
306 std::string session_string_value; | 347 std::string session_string_value; |
307 CHECK(args->GetString(0, &session_string_value)); | 348 CHECK(args->GetString(0, &session_string_value)); |
308 | 349 |
309 // Extract horizontal coordinate of the click within the application's client | 350 // Extract horizontal coordinate of the click relative to the origin of the |
310 // area. | 351 // screen coordinate system. |
311 double client_x; | 352 double screen_x; |
312 CHECK(args->GetDouble(1, &client_x)); | 353 CHECK(args->GetDouble(1, &screen_x)); |
313 | 354 |
314 // Extract vertical coordinate of the click within the application's client | 355 // Extract vertical coordinate of the click relative to the origin of the |
315 // area. | 356 // screen coordinate system. |
316 double client_y; | 357 double screen_y; |
317 CHECK(args->GetDouble(2, &client_y)); | 358 CHECK(args->GetDouble(2, &screen_y)); |
318 | 359 OtherDeviceMenuController* menu = new OtherDeviceMenuController( |
319 // TODO(vadimt): implement this method. | 360 web_ui(), |
320 } | 361 session_string_value, gfx::Point(screen_x, screen_y)); |
321 | 362 menu->ShowMenu(); |
Evan Stade
2012/10/24 22:51:34
wrong indent
jeremycho
2012/10/24 23:54:41
Done.
| |
322 bool ForeignSessionHandler::SessionTabToValue( | |
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 } | 363 } |
345 | 364 |
346 bool ForeignSessionHandler::SessionWindowToValue( | 365 bool ForeignSessionHandler::SessionWindowToValue( |
347 const SessionWindow& window, | 366 const SessionWindow& window, |
348 DictionaryValue* dictionary) { | 367 DictionaryValue* dictionary) { |
349 if (window.tabs.empty()) { | 368 if (window.tabs.empty()) { |
350 NOTREACHED(); | 369 NOTREACHED(); |
351 return false; | 370 return false; |
352 } | 371 } |
353 scoped_ptr<ListValue> tab_values(new ListValue()); | 372 scoped_ptr<ListValue> tab_values(new ListValue()); |
(...skipping 17 matching lines...) Expand all Loading... | |
371 dictionary->SetString("userVisibleTimestamp", | 390 dictionary->SetString("userVisibleTimestamp", |
372 last_synced < base::TimeDelta::FromMinutes(1) ? | 391 last_synced < base::TimeDelta::FromMinutes(1) ? |
373 l10n_util::GetStringUTF16(IDS_SYNC_TIME_JUST_NOW) : | 392 l10n_util::GetStringUTF16(IDS_SYNC_TIME_JUST_NOW) : |
374 TimeFormat::TimeElapsed(last_synced)); | 393 TimeFormat::TimeElapsed(last_synced)); |
375 dictionary->SetInteger("sessionId", window.window_id.id()); | 394 dictionary->SetInteger("sessionId", window.window_id.id()); |
376 dictionary->Set("tabs", tab_values.release()); | 395 dictionary->Set("tabs", tab_values.release()); |
377 return true; | 396 return true; |
378 } | 397 } |
379 | 398 |
380 } // namespace browser_sync | 399 } // namespace browser_sync |
OLD | NEW |