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