OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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/sync/glue/session_model_associator.h" |
| 6 |
| 7 #include <utility> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/string_util.h" |
| 11 #include "base/utf_string_conversions.h" |
| 12 #include "chrome/browser/profile.h" |
| 13 #include "chrome/browser/sessions/session_id.h" |
| 14 #include "chrome/browser/sync/profile_sync_service.h" |
| 15 #include "chrome/browser/sync/syncable/syncable.h" |
| 16 #include "chrome/common/notification_details.h" |
| 17 #include "chrome/common/notification_service.h" |
| 18 #include "chrome/common/url_constants.h" |
| 19 |
| 20 namespace browser_sync { |
| 21 |
| 22 namespace { |
| 23 |
| 24 static const char kNoSessionsFolderError[] = |
| 25 "Server did not create the top-level sessions node. We " |
| 26 "might be running against an out-of-date server."; |
| 27 |
| 28 } // namespace |
| 29 |
| 30 SessionModelAssociator::SessionModelAssociator( |
| 31 ProfileSyncService* sync_service) : sync_service_(sync_service) { |
| 32 DCHECK(CalledOnValidThread()); |
| 33 DCHECK(sync_service_); |
| 34 } |
| 35 |
| 36 SessionModelAssociator::~SessionModelAssociator() { |
| 37 DCHECK(CalledOnValidThread()); |
| 38 } |
| 39 |
| 40 // Sends a notification to ForeignSessionHandler to update the UI, because |
| 41 // the session corresponding to the id given has changed state. |
| 42 void SessionModelAssociator::Associate( |
| 43 const sync_pb::SessionSpecifics* specifics, int64 sync_id) { |
| 44 DCHECK(CalledOnValidThread()); |
| 45 NotificationService::current()->Notify( |
| 46 NotificationType::FOREIGN_SESSION_UPDATED, |
| 47 NotificationService::AllSources(), |
| 48 Details<int64>(&sync_id)); |
| 49 } |
| 50 |
| 51 bool SessionModelAssociator::AssociateModels() { |
| 52 DCHECK(CalledOnValidThread()); |
| 53 UpdateSyncModelDataFromClient(); |
| 54 return true; |
| 55 } |
| 56 |
| 57 bool SessionModelAssociator::ChromeModelHasUserCreatedNodes( |
| 58 bool* has_nodes) { |
| 59 DCHECK(CalledOnValidThread()); |
| 60 CHECK(has_nodes); |
| 61 // This is wrong, but this function is unused, anyway. |
| 62 *has_nodes = true; |
| 63 return true; |
| 64 } |
| 65 |
| 66 // Sends a notification to ForeignSessionHandler to update the UI, because |
| 67 // the session corresponding to the id given has been deleted. |
| 68 void SessionModelAssociator::Disassociate(int64 sync_id) { |
| 69 NotificationService::current()->Notify( |
| 70 NotificationType::FOREIGN_SESSION_DELETED, |
| 71 NotificationService::AllSources(), |
| 72 Details<int64>(&sync_id)); |
| 73 } |
| 74 |
| 75 const sync_pb::SessionSpecifics* SessionModelAssociator:: |
| 76 GetChromeNodeFromSyncId(int64 sync_id) { |
| 77 sync_api::ReadTransaction trans( |
| 78 sync_service_->backend()->GetUserShareHandle()); |
| 79 sync_api::ReadNode node(&trans); |
| 80 if (!node.InitByIdLookup(sync_id)) |
| 81 return NULL; |
| 82 return new sync_pb::SessionSpecifics(node.GetSessionSpecifics()); |
| 83 } |
| 84 |
| 85 bool SessionModelAssociator::GetSyncIdForTaggedNode(const std::string* tag, |
| 86 int64* sync_id) { |
| 87 sync_api::ReadTransaction trans( |
| 88 sync_service_->backend()->GetUserShareHandle()); |
| 89 sync_api::ReadNode node(&trans); |
| 90 if (!node.InitByClientTagLookup(syncable::SESSIONS, *tag)) |
| 91 return false; |
| 92 *sync_id = node.GetId(); |
| 93 return true; |
| 94 } |
| 95 |
| 96 int64 SessionModelAssociator::GetSyncIdFromChromeId(std::string id) { |
| 97 sync_api::ReadTransaction trans( |
| 98 sync_service_->backend()->GetUserShareHandle()); |
| 99 sync_api::ReadNode node(&trans); |
| 100 if (!node.InitByClientTagLookup(syncable::SESSIONS, id)) |
| 101 return sync_api::kInvalidId; |
| 102 return node.GetId(); |
| 103 } |
| 104 |
| 105 bool SessionModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) { |
| 106 DCHECK(CalledOnValidThread()); |
| 107 CHECK(has_nodes); |
| 108 *has_nodes = false; |
| 109 sync_api::ReadTransaction trans( |
| 110 sync_service_->backend()->GetUserShareHandle()); |
| 111 sync_api::ReadNode root(&trans); |
| 112 if (!root.InitByTagLookup(kSessionsTag)) { |
| 113 LOG(ERROR) << kNoSessionsFolderError; |
| 114 return false; |
| 115 } |
| 116 // The sync model has user created nodes iff the sessions folder has |
| 117 // any children. |
| 118 *has_nodes = root.GetFirstChildId() != sync_api::kInvalidId; |
| 119 return true; |
| 120 } |
| 121 |
| 122 std::string SessionModelAssociator::GetCurrentMachineTag() { |
| 123 if (current_machine_tag_.empty()) |
| 124 InitializeCurrentMachineTag(); |
| 125 DCHECK(!current_machine_tag_.empty()); |
| 126 return current_machine_tag_; |
| 127 } |
| 128 |
| 129 void SessionModelAssociator::AppendForeignSessionFromSpecifics( |
| 130 const sync_pb::SessionSpecifics* specifics, |
| 131 std::vector<ForeignSession*>* session) { |
| 132 ForeignSession* foreign_session = new ForeignSession(); |
| 133 foreign_session->foreign_tession_tag = specifics->session_tag(); |
| 134 session->insert(session->end(), foreign_session); |
| 135 for (int i = 0; i < specifics->session_window_size(); i++) { |
| 136 const sync_pb::SessionWindow* window = &specifics->session_window(i); |
| 137 SessionWindow* session_window = new SessionWindow(); |
| 138 PopulateSessionWindowFromSpecifics(session_window, window); |
| 139 foreign_session->windows.insert( |
| 140 foreign_session->windows.end(), session_window); |
| 141 } |
| 142 } |
| 143 |
| 144 // Fills the given vector with foreign session windows to restore. |
| 145 void SessionModelAssociator::AppendForeignSessionWithID(int64 id, |
| 146 std::vector<ForeignSession*>* session, sync_api::BaseTransaction* trans) { |
| 147 if (id == sync_api::kInvalidId) |
| 148 return; |
| 149 sync_api::ReadNode node(trans); |
| 150 if (!node.InitByIdLookup(id)) |
| 151 return; |
| 152 const sync_pb::SessionSpecifics* ref = &node.GetSessionSpecifics(); |
| 153 AppendForeignSessionFromSpecifics(ref, session); |
| 154 } |
| 155 |
| 156 void SessionModelAssociator::UpdateSyncModelDataFromClient() { |
| 157 DCHECK(CalledOnValidThread()); |
| 158 SessionService::SessionCallback* callback = |
| 159 NewCallback(this, &SessionModelAssociator::OnGotSession); |
| 160 // TODO(jerrica): Stop current race condition, possibly make new method in |
| 161 // session service, which only grabs the windows from memory. |
| 162 GetSessionService()->GetCurrentSession(&consumer_, callback); |
| 163 } |
| 164 |
| 165 bool SessionModelAssociator::GetSessionDataFromSyncModel( |
| 166 std::vector<ForeignSession*>* sessions) { |
| 167 std::vector<const sync_pb::SessionSpecifics*> specifics; |
| 168 DCHECK(CalledOnValidThread()); |
| 169 sync_api::ReadTransaction trans( |
| 170 sync_service_->backend()->GetUserShareHandle()); |
| 171 sync_api::ReadNode root(&trans); |
| 172 if (!root.InitByTagLookup(kSessionsTag)) { |
| 173 LOG(ERROR) << kNoSessionsFolderError; |
| 174 return false; |
| 175 } |
| 176 sync_api::ReadNode current_machine(&trans); |
| 177 int64 current_id = (current_machine.InitByClientTagLookup(syncable::SESSIONS, |
| 178 GetCurrentMachineTag())) ? current_machine.GetId() : sync_api::kInvalidId; |
| 179 // Iterate through the nodes and populate the session model. |
| 180 int64 id = root.GetFirstChildId(); |
| 181 while (id != sync_api::kInvalidId) { |
| 182 sync_api::ReadNode sync_node(&trans); |
| 183 if (!sync_node.InitByIdLookup(id)) { |
| 184 LOG(ERROR) << "Failed to fetch sync node for id " << id; |
| 185 return false; |
| 186 } |
| 187 if (id != current_id) { |
| 188 specifics.insert(specifics.end(), &sync_node.GetSessionSpecifics()); |
| 189 } |
| 190 id = sync_node.GetSuccessorId(); |
| 191 } |
| 192 for (std::vector<const sync_pb::SessionSpecifics*>::const_iterator i = |
| 193 specifics.begin(); i != specifics.end(); ++i) { |
| 194 AppendForeignSessionFromSpecifics(*i, sessions); |
| 195 } |
| 196 return true; |
| 197 } |
| 198 |
| 199 SessionService* SessionModelAssociator::GetSessionService() { |
| 200 DCHECK(sync_service_); |
| 201 Profile* profile = sync_service_->profile(); |
| 202 DCHECK(profile); |
| 203 SessionService* sessions_service = profile->GetSessionService(); |
| 204 DCHECK(sessions_service); |
| 205 return sessions_service; |
| 206 } |
| 207 |
| 208 void SessionModelAssociator::InitializeCurrentMachineTag() { |
| 209 sync_api::WriteTransaction trans(sync_service_->backend()-> |
| 210 GetUserShareHandle()); |
| 211 syncable::Directory* dir = |
| 212 trans.GetWrappedWriteTrans()->directory(); |
| 213 current_machine_tag_ = "session_sync" + dir->cache_guid(); |
| 214 } |
| 215 |
| 216 // See PopulateSessionSpecificsTab for use. May add functionality that includes |
| 217 // the state later. |
| 218 void SessionModelAssociator::PopulateSessionSpecificsNavigation( |
| 219 const TabNavigation* navigation, sync_pb::TabNavigation* tab_navigation) { |
| 220 tab_navigation->set_index(navigation->index()); |
| 221 tab_navigation->set_virtual_url(navigation->virtual_url().spec()); |
| 222 tab_navigation->set_referrer(navigation->referrer().spec()); |
| 223 tab_navigation->set_title(UTF16ToUTF8(navigation->title())); |
| 224 switch (navigation->transition()) { |
| 225 case PageTransition::LINK: |
| 226 tab_navigation->set_page_transition( |
| 227 sync_pb::TabNavigation_PageTransition_LINK); |
| 228 break; |
| 229 case PageTransition::TYPED: |
| 230 tab_navigation->set_page_transition( |
| 231 sync_pb::TabNavigation_PageTransition_TYPED); |
| 232 break; |
| 233 case PageTransition::AUTO_BOOKMARK: |
| 234 tab_navigation->set_page_transition( |
| 235 sync_pb::TabNavigation_PageTransition_AUTO_BOOKMARK); |
| 236 break; |
| 237 case PageTransition::AUTO_SUBFRAME: |
| 238 tab_navigation->set_page_transition( |
| 239 sync_pb::TabNavigation_PageTransition_AUTO_SUBFRAME); |
| 240 break; |
| 241 case PageTransition::MANUAL_SUBFRAME: |
| 242 tab_navigation->set_page_transition( |
| 243 sync_pb::TabNavigation_PageTransition_MANUAL_SUBFRAME); |
| 244 break; |
| 245 case PageTransition::GENERATED: |
| 246 tab_navigation->set_page_transition( |
| 247 sync_pb::TabNavigation_PageTransition_GENERATED); |
| 248 break; |
| 249 case PageTransition::START_PAGE: |
| 250 tab_navigation->set_page_transition( |
| 251 sync_pb::TabNavigation_PageTransition_START_PAGE); |
| 252 break; |
| 253 case PageTransition::FORM_SUBMIT: |
| 254 tab_navigation->set_page_transition( |
| 255 sync_pb::TabNavigation_PageTransition_FORM_SUBMIT); |
| 256 break; |
| 257 case PageTransition::RELOAD: |
| 258 tab_navigation->set_page_transition( |
| 259 sync_pb::TabNavigation_PageTransition_RELOAD); |
| 260 break; |
| 261 case PageTransition::KEYWORD: |
| 262 tab_navigation->set_page_transition( |
| 263 sync_pb::TabNavigation_PageTransition_KEYWORD); |
| 264 break; |
| 265 case PageTransition::KEYWORD_GENERATED: |
| 266 tab_navigation->set_page_transition( |
| 267 sync_pb::TabNavigation_PageTransition_KEYWORD_GENERATED); |
| 268 break; |
| 269 case PageTransition::CHAIN_START: |
| 270 tab_navigation->set_page_transition( |
| 271 sync_pb::TabNavigation_PageTransition_CHAIN_START); |
| 272 break; |
| 273 case PageTransition::CHAIN_END: |
| 274 tab_navigation->set_page_transition( |
| 275 sync_pb::TabNavigation_PageTransition_CHAIN_END); |
| 276 break; |
| 277 case PageTransition::CLIENT_REDIRECT: |
| 278 tab_navigation->set_navigation_qualifier( |
| 279 sync_pb::TabNavigation_PageTransitionQualifier_CLIENT_REDIRECT); |
| 280 break; |
| 281 case PageTransition::SERVER_REDIRECT: |
| 282 tab_navigation->set_navigation_qualifier( |
| 283 sync_pb::TabNavigation_PageTransitionQualifier_SERVER_REDIRECT); |
| 284 break; |
| 285 default: |
| 286 tab_navigation->set_page_transition( |
| 287 sync_pb::TabNavigation_PageTransition_TYPED); |
| 288 } |
| 289 } |
| 290 |
| 291 // See PopulateSessionSpecificsWindow for use. |
| 292 void SessionModelAssociator::PopulateSessionSpecificsTab( |
| 293 const SessionTab* tab, sync_pb::SessionTab* session_tab) { |
| 294 session_tab->set_tab_visual_index(tab->tab_visual_index); |
| 295 session_tab->set_current_navigation_index( |
| 296 tab->current_navigation_index); |
| 297 session_tab->set_pinned(tab->pinned); |
| 298 session_tab->set_extension_app_id(tab->extension_app_id); |
| 299 for (std::vector<TabNavigation>::const_iterator i3 = |
| 300 tab->navigations.begin(); i3 != tab->navigations.end(); ++i3) { |
| 301 const TabNavigation navigation = *i3; |
| 302 sync_pb::TabNavigation* tab_navigation = |
| 303 session_tab->add_navigation(); |
| 304 PopulateSessionSpecificsNavigation(&navigation, tab_navigation); |
| 305 } |
| 306 } |
| 307 |
| 308 // Called when populating session specifics to send to the sync model, called |
| 309 // when associating models, or updating the sync model. |
| 310 void SessionModelAssociator::PopulateSessionSpecificsWindow( |
| 311 const SessionWindow* window, sync_pb::SessionWindow* session_window) { |
| 312 session_window->set_selected_tab_index(window->selected_tab_index); |
| 313 if (window->type == 1) { |
| 314 session_window->set_browser_type( |
| 315 sync_pb::SessionWindow_BrowserType_TYPE_NORMAL); |
| 316 } else { |
| 317 session_window->set_browser_type( |
| 318 sync_pb::SessionWindow_BrowserType_TYPE_POPUP); |
| 319 } |
| 320 for (std::vector<SessionTab*>::const_iterator i2 = window->tabs.begin(); |
| 321 i2 != window->tabs.end(); ++i2) { |
| 322 const SessionTab* tab = *i2; |
| 323 if (tab->navigations.at(tab->current_navigation_index).virtual_url() == |
| 324 GURL(chrome::kChromeUINewTabURL)) { |
| 325 continue; |
| 326 } |
| 327 sync_pb::SessionTab* session_tab = session_window->add_session_tab(); |
| 328 PopulateSessionSpecificsTab(tab, session_tab); |
| 329 } |
| 330 } |
| 331 |
| 332 bool SessionModelAssociator::WindowHasNoTabsToSync( |
| 333 const SessionWindow* window) { |
| 334 int num_populated = 0; |
| 335 for (std::vector<SessionTab*>::const_iterator i = window->tabs.begin(); |
| 336 i != window->tabs.end(); ++i) { |
| 337 const SessionTab* tab = *i; |
| 338 if (tab->navigations.at(tab->current_navigation_index).virtual_url() == |
| 339 GURL(chrome::kChromeUINewTabURL)) { |
| 340 continue; |
| 341 } |
| 342 num_populated++; |
| 343 } |
| 344 if (num_populated == 0) |
| 345 return true; |
| 346 return false; |
| 347 } |
| 348 |
| 349 void SessionModelAssociator::OnGotSession(int handle, |
| 350 std::vector<SessionWindow*>* windows) { |
| 351 sync_pb::SessionSpecifics session; |
| 352 // Set the tag, then iterate through the vector of windows, extracting the |
| 353 // window data, along with the tabs data and tab navigation data to populate |
| 354 // the session specifics. |
| 355 session.set_session_tag(GetCurrentMachineTag()); |
| 356 for (std::vector<SessionWindow*>::const_iterator i = windows->begin(); |
| 357 i != windows->end(); ++i) { |
| 358 const SessionWindow* window = *i; |
| 359 if (WindowHasNoTabsToSync(window)) { |
| 360 continue; |
| 361 } |
| 362 sync_pb::SessionWindow* session_window = session.add_session_window(); |
| 363 PopulateSessionSpecificsWindow(window, session_window); |
| 364 } |
| 365 bool has_nodes = false; |
| 366 if (!SyncModelHasUserCreatedNodes(&has_nodes)) |
| 367 return; |
| 368 if (session.session_window_size() == 0 && has_nodes) |
| 369 return; |
| 370 sync_api::WriteTransaction trans( |
| 371 sync_service_->backend()->GetUserShareHandle()); |
| 372 sync_api::ReadNode root(&trans); |
| 373 if (!root.InitByTagLookup(kSessionsTag)) { |
| 374 LOG(ERROR) << kNoSessionsFolderError; |
| 375 return; |
| 376 } |
| 377 UpdateSyncModel(&session, &trans, &root); |
| 378 } |
| 379 |
| 380 void SessionModelAssociator::AppendSessionTabNavigation( |
| 381 std::vector<TabNavigation>* navigations, |
| 382 const sync_pb::TabNavigation* navigation) { |
| 383 int index = 0; |
| 384 GURL virtual_url; |
| 385 GURL referrer; |
| 386 string16 title; |
| 387 std::string state; |
| 388 PageTransition::Type transition(PageTransition::LINK); |
| 389 if (navigation->has_index()) |
| 390 index = navigation->index(); |
| 391 if (navigation->has_virtual_url()) { |
| 392 GURL gurl(navigation->virtual_url()); |
| 393 virtual_url = gurl; |
| 394 } |
| 395 if (navigation->has_referrer()) { |
| 396 GURL gurl(navigation->referrer()); |
| 397 referrer = gurl; |
| 398 } |
| 399 if (navigation->has_title()) |
| 400 title = UTF8ToUTF16(navigation->title()); |
| 401 if (navigation->has_page_transition() || |
| 402 navigation->has_navigation_qualifier()) { |
| 403 switch (navigation->page_transition()) { |
| 404 case sync_pb::TabNavigation_PageTransition_LINK: |
| 405 transition = PageTransition::LINK; |
| 406 break; |
| 407 case sync_pb::TabNavigation_PageTransition_TYPED: |
| 408 transition = PageTransition::TYPED; |
| 409 break; |
| 410 case sync_pb::TabNavigation_PageTransition_AUTO_BOOKMARK: |
| 411 transition = PageTransition::AUTO_BOOKMARK; |
| 412 break; |
| 413 case sync_pb::TabNavigation_PageTransition_AUTO_SUBFRAME: |
| 414 transition = PageTransition::AUTO_SUBFRAME; |
| 415 break; |
| 416 case sync_pb::TabNavigation_PageTransition_MANUAL_SUBFRAME: |
| 417 transition = PageTransition::MANUAL_SUBFRAME; |
| 418 break; |
| 419 case sync_pb::TabNavigation_PageTransition_GENERATED: |
| 420 transition = PageTransition::GENERATED; |
| 421 break; |
| 422 case sync_pb::TabNavigation_PageTransition_START_PAGE: |
| 423 transition = PageTransition::START_PAGE; |
| 424 break; |
| 425 case sync_pb::TabNavigation_PageTransition_FORM_SUBMIT: |
| 426 transition = PageTransition::FORM_SUBMIT; |
| 427 break; |
| 428 case sync_pb::TabNavigation_PageTransition_RELOAD: |
| 429 transition = PageTransition::RELOAD; |
| 430 break; |
| 431 case sync_pb::TabNavigation_PageTransition_KEYWORD: |
| 432 transition = PageTransition::KEYWORD; |
| 433 break; |
| 434 case sync_pb::TabNavigation_PageTransition_KEYWORD_GENERATED: |
| 435 transition = PageTransition::KEYWORD_GENERATED; |
| 436 break; |
| 437 case sync_pb::TabNavigation_PageTransition_CHAIN_START: |
| 438 transition = sync_pb::TabNavigation_PageTransition_CHAIN_START; |
| 439 break; |
| 440 case sync_pb::TabNavigation_PageTransition_CHAIN_END: |
| 441 transition = PageTransition::CHAIN_END; |
| 442 break; |
| 443 default: |
| 444 switch (navigation->navigation_qualifier()) { |
| 445 case sync_pb:: |
| 446 TabNavigation_PageTransitionQualifier_CLIENT_REDIRECT: |
| 447 transition = PageTransition::CLIENT_REDIRECT; |
| 448 break; |
| 449 case sync_pb:: |
| 450 TabNavigation_PageTransitionQualifier_SERVER_REDIRECT: |
| 451 transition = PageTransition::SERVER_REDIRECT; |
| 452 break; |
| 453 default: |
| 454 transition = PageTransition::TYPED; |
| 455 } |
| 456 } |
| 457 } |
| 458 TabNavigation tab_navigation(index, virtual_url, referrer, title, state, |
| 459 transition); |
| 460 navigations->insert(navigations->end(), tab_navigation); |
| 461 } |
| 462 |
| 463 void SessionModelAssociator::PopulateSessionTabFromSpecifics( |
| 464 SessionTab* session_tab, |
| 465 const sync_pb::SessionTab* tab, SessionID id) { |
| 466 session_tab->window_id = id; |
| 467 SessionID tabID; |
| 468 session_tab->tab_id = tabID; |
| 469 if (tab->has_tab_visual_index()) |
| 470 session_tab->tab_visual_index = tab->tab_visual_index(); |
| 471 if (tab->has_current_navigation_index()) { |
| 472 session_tab->current_navigation_index = |
| 473 tab->current_navigation_index(); |
| 474 } |
| 475 if (tab->has_pinned()) |
| 476 session_tab->pinned = tab->pinned(); |
| 477 if (tab->has_extension_app_id()) |
| 478 session_tab->extension_app_id = tab->extension_app_id(); |
| 479 for (int i3 = 0; i3 < tab->navigation_size(); i3++) { |
| 480 const sync_pb::TabNavigation* navigation = &tab->navigation(i3); |
| 481 AppendSessionTabNavigation(&session_tab->navigations, navigation); |
| 482 } |
| 483 } |
| 484 |
| 485 void SessionModelAssociator::PopulateSessionWindowFromSpecifics( |
| 486 SessionWindow* session_window, const sync_pb::SessionWindow* window) { |
| 487 SessionID id; |
| 488 session_window->window_id = id; |
| 489 if (window->has_selected_tab_index()) |
| 490 session_window->selected_tab_index = window->selected_tab_index(); |
| 491 if (window->has_browser_type()) { |
| 492 if (window->browser_type() == |
| 493 sync_pb::SessionWindow_BrowserType_TYPE_NORMAL) { |
| 494 session_window->type = 1; |
| 495 } else { |
| 496 session_window->type = 2; |
| 497 } |
| 498 } |
| 499 for (int i = 0; i < window->session_tab_size(); i++) { |
| 500 const sync_pb::SessionTab& tab = window->session_tab(i); |
| 501 SessionTab* session_tab = new SessionTab(); |
| 502 PopulateSessionTabFromSpecifics(session_tab, &tab, id); |
| 503 session_window->tabs.insert(session_window->tabs.end(), session_tab); |
| 504 } |
| 505 } |
| 506 |
| 507 bool SessionModelAssociator::UpdateSyncModel( |
| 508 sync_pb::SessionSpecifics* session_data, |
| 509 sync_api::WriteTransaction* trans, |
| 510 const sync_api::ReadNode* root) { |
| 511 const std::string id = session_data->session_tag(); |
| 512 sync_api::WriteNode write_node(trans); |
| 513 if (!write_node.InitByClientTagLookup(syncable::SESSIONS, id)) { |
| 514 sync_api::WriteNode create_node(trans); |
| 515 if (!create_node.InitUniqueByCreation(syncable::SESSIONS, *root, id)) { |
| 516 LOG(ERROR) << "Could not create node for session " << id; |
| 517 return false; |
| 518 } |
| 519 create_node.SetSessionSpecifics(*session_data); |
| 520 return true; |
| 521 } |
| 522 write_node.SetSessionSpecifics(*session_data); |
| 523 return true; |
| 524 } |
| 525 |
| 526 } // namespace browser_sync |
| 527 |
OLD | NEW |