OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/sync_sessions/sessions_sync_manager.h" | 5 #include "components/sync_sessions/sessions_sync_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 merge_result.set_error(error_handler_->CreateAndUploadError( | 149 merge_result.set_error(error_handler_->CreateAndUploadError( |
150 FROM_HERE, "Failed to get local device info.")); | 150 FROM_HERE, "Failed to get local device info.")); |
151 return merge_result; | 151 return merge_result; |
152 } | 152 } |
153 | 153 |
154 session_tracker_.SetLocalSessionTag(current_machine_tag_); | 154 session_tracker_.SetLocalSessionTag(current_machine_tag_); |
155 | 155 |
156 syncer::SyncChangeList new_changes; | 156 syncer::SyncChangeList new_changes; |
157 | 157 |
158 // First, we iterate over sync data to update our session_tracker_. | 158 // First, we iterate over sync data to update our session_tracker_. |
159 if (!InitFromSyncModel(initial_sync_data, &new_changes)) { | 159 syncer::SyncDataList restored_tabs; |
| 160 if (!InitFromSyncModel(initial_sync_data, &restored_tabs, &new_changes)) { |
160 // The sync db didn't have a header node for us. Create one. | 161 // The sync db didn't have a header node for us. Create one. |
161 sync_pb::EntitySpecifics specifics; | 162 sync_pb::EntitySpecifics specifics; |
162 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); | 163 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); |
163 base_specifics->set_session_tag(current_machine_tag()); | 164 base_specifics->set_session_tag(current_machine_tag()); |
164 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); | 165 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); |
165 header_s->set_client_name(current_session_name_); | 166 header_s->set_client_name(current_session_name_); |
166 header_s->set_device_type(local_device_info->device_type()); | 167 header_s->set_device_type(local_device_info->device_type()); |
167 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 168 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
168 current_machine_tag(), current_session_name_, specifics); | 169 current_machine_tag(), current_session_name_, specifics); |
169 new_changes.push_back( | 170 new_changes.push_back( |
170 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); | 171 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); |
171 } | 172 } |
172 | 173 |
173 #if defined(OS_ANDROID) | 174 #if defined(OS_ANDROID) |
174 std::string sync_machine_tag( | 175 std::string sync_machine_tag( |
175 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); | 176 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); |
176 if (current_machine_tag_.compare(sync_machine_tag) != 0) | 177 if (current_machine_tag_.compare(sync_machine_tag) != 0) |
177 DeleteForeignSessionInternal(sync_machine_tag, &new_changes); | 178 DeleteForeignSessionInternal(sync_machine_tag, &new_changes); |
178 #endif | 179 #endif |
179 | 180 |
180 // Check if anything has changed on the local client side. | 181 // Check if anything has changed on the local client side. |
181 AssociateWindows(RELOAD_TABS, &new_changes); | 182 AssociateWindows(RELOAD_TABS, restored_tabs, &new_changes); |
182 local_tab_pool_out_of_sync_ = false; | 183 local_tab_pool_out_of_sync_ = false; |
183 | 184 |
184 merge_result.set_error( | 185 merge_result.set_error( |
185 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); | 186 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); |
186 | 187 |
187 local_event_router_->StartRoutingTo(this); | 188 local_event_router_->StartRoutingTo(this); |
188 return merge_result; | 189 return merge_result; |
189 } | 190 } |
190 | 191 |
191 void SessionsSyncManager::AssociateWindows( | 192 void SessionsSyncManager::AssociateWindows( |
192 ReloadTabsOption option, | 193 ReloadTabsOption option, |
| 194 const syncer::SyncDataList& restored_tabs, |
193 syncer::SyncChangeList* change_output) { | 195 syncer::SyncChangeList* change_output) { |
194 const std::string local_tag = current_machine_tag(); | 196 const std::string local_tag = current_machine_tag(); |
195 sync_pb::SessionSpecifics specifics; | 197 sync_pb::SessionSpecifics specifics; |
196 specifics.set_session_tag(local_tag); | 198 specifics.set_session_tag(local_tag); |
197 sync_pb::SessionHeader* header_s = specifics.mutable_header(); | 199 sync_pb::SessionHeader* header_s = specifics.mutable_header(); |
198 SyncedSession* current_session = session_tracker_.GetSession(local_tag); | 200 SyncedSession* current_session = session_tracker_.GetSession(local_tag); |
199 current_session->modified_time = base::Time::Now(); | 201 current_session->modified_time = base::Time::Now(); |
200 header_s->set_client_name(current_session_name_); | 202 header_s->set_client_name(current_session_name_); |
201 // SessionDataTypeController ensures that the local device info | 203 // SessionDataTypeController ensures that the local device info |
202 // is available before activating this datatype. | 204 // is available before activating this datatype. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 | 266 |
265 if (synced_tab->IsPlaceholderTab()) { | 267 if (synced_tab->IsPlaceholderTab()) { |
266 // For tabs without WebContents update the |tab_id| and |window_id|, | 268 // For tabs without WebContents update the |tab_id| and |window_id|, |
267 // as it could have changed after a session restore. | 269 // as it could have changed after a session restore. |
268 // Note: We cannot check if a tab is valid if it has no WebContents. | 270 // Note: We cannot check if a tab is valid if it has no WebContents. |
269 // We assume any such tab is valid and leave the contents of | 271 // We assume any such tab is valid and leave the contents of |
270 // corresponding sync node unchanged. | 272 // corresponding sync node unchanged. |
271 if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID && | 273 if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID && |
272 tab_id > TabNodePool::kInvalidTabID) { | 274 tab_id > TabNodePool::kInvalidTabID) { |
273 AssociateRestoredPlaceholderTab(*synced_tab, tab_id, window_id, | 275 AssociateRestoredPlaceholderTab(*synced_tab, tab_id, window_id, |
274 change_output); | 276 restored_tabs, change_output); |
275 found_tabs = true; | 277 found_tabs = true; |
276 window_s.add_tab(tab_id); | 278 window_s.add_tab(tab_id); |
277 } | 279 } |
278 continue; | 280 continue; |
279 } | 281 } |
280 | 282 |
281 if (RELOAD_TABS == option) | 283 if (RELOAD_TABS == option) |
282 AssociateTab(synced_tab, change_output); | 284 AssociateTab(synced_tab, change_output); |
283 | 285 |
284 // If the tab is valid, it would have been added to the tracker either | 286 // If the tab is valid, it would have been added to the tracker either |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 | 345 |
344 if (local_tab_map_iter == local_tab_map_.end()) { | 346 if (local_tab_map_iter == local_tab_map_.end()) { |
345 int tab_node_id = tab->GetSyncId(); | 347 int tab_node_id = tab->GetSyncId(); |
346 // If there is an old sync node for the tab, reuse it. If this is a new | 348 // If there is an old sync node for the tab, reuse it. If this is a new |
347 // tab, get a sync node for it. | 349 // tab, get a sync node for it. |
348 if (!local_tab_pool_.IsUnassociatedTabNode(tab_node_id)) { | 350 if (!local_tab_pool_.IsUnassociatedTabNode(tab_node_id)) { |
349 tab_node_id = local_tab_pool_.GetFreeTabNode(change_output); | 351 tab_node_id = local_tab_pool_.GetFreeTabNode(change_output); |
350 tab->SetSyncId(tab_node_id); | 352 tab->SetSyncId(tab_node_id); |
351 } | 353 } |
352 local_tab_pool_.AssociateTabNode(tab_node_id, tab_id); | 354 local_tab_pool_.AssociateTabNode(tab_node_id, tab_id); |
353 tab_link = new TabLink(tab_node_id); | 355 tab_link = new TabLink(tab_node_id, tab); |
354 local_tab_map_[tab_id] = make_linked_ptr<TabLink>(tab_link); | 356 local_tab_map_[tab_id] = make_linked_ptr<TabLink>(tab_link); |
355 } else { | 357 } else { |
| 358 // This tab is already associated with a sync node, reuse it. |
| 359 // Note: on some platforms the tab object may have changed, so we ensure |
| 360 // the tab link is up to date. |
356 tab_link = local_tab_map_iter->second.get(); | 361 tab_link = local_tab_map_iter->second.get(); |
| 362 local_tab_map_iter->second->set_tab(tab); |
357 } | 363 } |
358 DCHECK(tab_link); | 364 DCHECK(tab_link); |
359 DCHECK_NE(tab_link->tab_node_id(), TabNodePool::kInvalidTabNodeID); | 365 DCHECK_NE(tab_link->tab_node_id(), TabNodePool::kInvalidTabNodeID); |
360 DVLOG(1) << "Reloading tab " << tab_id << " from window " | 366 DVLOG(1) << "Reloading tab " << tab_id << " from window " |
361 << tab->GetWindowId(); | 367 << tab->GetWindowId(); |
362 | 368 |
363 // Write to sync model. | 369 // Write to sync model. |
364 sync_pb::EntitySpecifics specifics; | 370 sync_pb::EntitySpecifics specifics; |
365 LocalTabDelegateToSpecifics(*tab, specifics.mutable_session()); | 371 LocalTabDelegateToSpecifics(*tab, specifics.mutable_session()); |
366 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 372 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 DCHECK(!local_tab_pool_out_of_sync_); | 438 DCHECK(!local_tab_pool_out_of_sync_); |
433 return; | 439 return; |
434 } | 440 } |
435 | 441 |
436 syncer::SyncChangeList changes; | 442 syncer::SyncChangeList changes; |
437 AssociateTab(modified_tab, &changes); | 443 AssociateTab(modified_tab, &changes); |
438 // Note, we always associate windows because it's possible a tab became | 444 // Note, we always associate windows because it's possible a tab became |
439 // "interesting" by going to a valid URL, in which case it needs to be added | 445 // "interesting" by going to a valid URL, in which case it needs to be added |
440 // to the window's tab information. Similarly, if a tab became | 446 // to the window's tab information. Similarly, if a tab became |
441 // "uninteresting", we remove it from the window's tab information. | 447 // "uninteresting", we remove it from the window's tab information. |
442 AssociateWindows(DONT_RELOAD_TABS, &changes); | 448 AssociateWindows(DONT_RELOAD_TABS, syncer::SyncDataList(), &changes); |
443 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); | 449 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); |
444 } | 450 } |
445 | 451 |
446 void SessionsSyncManager::OnFaviconsChanged(const std::set<GURL>& page_urls, | 452 void SessionsSyncManager::OnFaviconsChanged(const std::set<GURL>& page_urls, |
447 const GURL& /* icon_url */) { | 453 const GURL& /* icon_url */) { |
448 // TODO(zea): consider a separate container for tabs with outstanding favicon | 454 // TODO(zea): consider a separate container for tabs with outstanding favicon |
449 // loads so we don't have to iterate through all tabs comparing urls. | 455 // loads so we don't have to iterate through all tabs comparing urls. |
450 for (const GURL& page_url : page_urls) { | 456 for (const GURL& page_url : page_urls) { |
451 for (TabLinksMap::iterator tab_iter = local_tab_map_.begin(); | 457 for (TabLinksMap::iterator tab_iter = local_tab_map_.begin(); |
452 tab_iter != local_tab_map_.end(); ++tab_iter) { | 458 tab_iter != local_tab_map_.end(); ++tab_iter) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 break; | 573 break; |
568 case syncer::SyncChange::ACTION_ADD: | 574 case syncer::SyncChange::ACTION_ADD: |
569 case syncer::SyncChange::ACTION_UPDATE: | 575 case syncer::SyncChange::ACTION_UPDATE: |
570 if (current_machine_tag() == session.session_tag()) { | 576 if (current_machine_tag() == session.session_tag()) { |
571 // We should only ever receive a change to our own machine's session | 577 // We should only ever receive a change to our own machine's session |
572 // info if encryption was turned on. In that case, the data is still | 578 // info if encryption was turned on. In that case, the data is still |
573 // the same, so we can ignore. | 579 // the same, so we can ignore. |
574 LOG(WARNING) << "Dropping modification to local session."; | 580 LOG(WARNING) << "Dropping modification to local session."; |
575 return syncer::SyncError(); | 581 return syncer::SyncError(); |
576 } | 582 } |
577 UpdateTrackerWithSpecifics( | 583 UpdateTrackerWithForeignSession( |
578 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); | 584 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); |
579 break; | 585 break; |
580 default: | 586 default: |
581 NOTREACHED() << "Processing sync changes failed, unknown change type."; | 587 NOTREACHED() << "Processing sync changes failed, unknown change type."; |
582 } | 588 } |
583 } | 589 } |
584 | 590 |
585 if (!sessions_updated_callback_.is_null()) | 591 if (!sessions_updated_callback_.is_null()) |
586 sessions_updated_callback_.Run(); | 592 sessions_updated_callback_.Run(); |
587 return syncer::SyncError(); | 593 return syncer::SyncError(); |
(...skipping 17 matching lines...) Expand all Loading... |
605 std::vector<const SyncedSession*>* sessions) { | 611 std::vector<const SyncedSession*>* sessions) { |
606 if (!session_tracker_.LookupAllForeignSessions( | 612 if (!session_tracker_.LookupAllForeignSessions( |
607 sessions, SyncedSessionTracker::PRESENTABLE)) | 613 sessions, SyncedSessionTracker::PRESENTABLE)) |
608 return false; | 614 return false; |
609 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); | 615 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); |
610 return true; | 616 return true; |
611 } | 617 } |
612 | 618 |
613 bool SessionsSyncManager::InitFromSyncModel( | 619 bool SessionsSyncManager::InitFromSyncModel( |
614 const syncer::SyncDataList& sync_data, | 620 const syncer::SyncDataList& sync_data, |
| 621 syncer::SyncDataList* restored_tabs, |
615 syncer::SyncChangeList* new_changes) { | 622 syncer::SyncChangeList* new_changes) { |
616 bool found_current_header = false; | 623 bool found_current_header = false; |
617 int bad_foreign_hash_count = 0; | 624 int bad_foreign_hash_count = 0; |
618 for (syncer::SyncDataList::const_iterator it = sync_data.begin(); | 625 for (syncer::SyncDataList::const_iterator it = sync_data.begin(); |
619 it != sync_data.end(); ++it) { | 626 it != sync_data.end(); ++it) { |
620 const syncer::SyncData& data = *it; | 627 const syncer::SyncData& data = *it; |
621 DCHECK(data.GetSpecifics().has_session()); | 628 DCHECK(data.GetSpecifics().has_session()); |
622 syncer::SyncDataRemote remote(data); | 629 syncer::SyncDataRemote remote(data); |
623 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); | 630 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); |
624 if (specifics.session_tag().empty() || | 631 if (specifics.session_tag().empty() || |
625 (specifics.has_tab() && | 632 (specifics.has_tab() && |
626 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { | 633 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { |
627 syncer::SyncChange tombstone(TombstoneTab(specifics)); | 634 syncer::SyncChange tombstone(TombstoneTab(specifics)); |
628 if (tombstone.IsValid()) | 635 if (tombstone.IsValid()) |
629 new_changes->push_back(tombstone); | 636 new_changes->push_back(tombstone); |
630 } else if (specifics.session_tag() != current_machine_tag()) { | 637 } else if (specifics.session_tag() != current_machine_tag()) { |
631 if (TagHashFromSpecifics(specifics) == remote.GetClientTagHash()) { | 638 if (TagHashFromSpecifics(specifics) == remote.GetClientTagHash()) { |
632 UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime()); | 639 UpdateTrackerWithForeignSession(specifics, remote.GetModifiedTime()); |
633 } else { | 640 } else { |
634 // In the past, like years ago, we believe that some session data was | 641 // In the past, like years ago, we believe that some session data was |
635 // created with bad tag hashes. This causes any change this client makes | 642 // created with bad tag hashes. This causes any change this client makes |
636 // to that foreign data (like deletion through garbage collection) to | 643 // to that foreign data (like deletion through garbage collection) to |
637 // trigger a data type error because the tag looking mechanism fails. So | 644 // trigger a data type error because the tag looking mechanism fails. So |
638 // look for these and delete via remote SyncData, which uses a server id | 645 // look for these and delete via remote SyncData, which uses a server id |
639 // lookup mechanism instead, see crbug.com/604657. | 646 // lookup mechanism instead, see crbug.com/604657. |
640 bad_foreign_hash_count++; | 647 bad_foreign_hash_count++; |
641 new_changes->push_back( | 648 new_changes->push_back( |
642 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, remote)); | 649 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, remote)); |
643 } | 650 } |
644 } else { | 651 } else { |
645 // This is previously stored local session information. | 652 // This is previously stored local session information. |
646 if (specifics.has_header() && !found_current_header) { | 653 if (specifics.has_header() && !found_current_header) { |
647 // This is our previous header node, reuse it. | 654 // This is our previous header node, reuse it. |
648 found_current_header = true; | 655 found_current_header = true; |
649 if (specifics.header().has_client_name()) | 656 if (specifics.header().has_client_name()) |
650 current_session_name_ = specifics.header().client_name(); | 657 current_session_name_ = specifics.header().client_name(); |
651 | |
652 // TODO(zea): crbug.com/639009 update the tracker with the specifics | |
653 // from the header node as well. This will be necessary to preserve | |
654 // the set of open tabs when a custom tab is opened. | |
655 } else { | 658 } else { |
656 if (specifics.has_header() || !specifics.has_tab()) { | 659 if (specifics.has_header() || !specifics.has_tab()) { |
657 LOG(WARNING) << "Found more than one session header node with local " | 660 LOG(WARNING) << "Found more than one session header node with local " |
658 << "tag."; | 661 << "tag."; |
659 syncer::SyncChange tombstone(TombstoneTab(specifics)); | 662 syncer::SyncChange tombstone(TombstoneTab(specifics)); |
660 if (tombstone.IsValid()) | 663 if (tombstone.IsValid()) |
661 new_changes->push_back(tombstone); | 664 new_changes->push_back(tombstone); |
662 } else { | 665 } else { |
663 // This is a valid old tab node, reassociate it and add it to the | 666 // This is a valid old tab node, add it to the pool so it can be |
664 // tracker. | 667 // reused for reassociation. |
665 local_tab_map_[specifics.tab().tab_id()] = | |
666 make_linked_ptr<TabLink>(new TabLink(specifics.tab_node_id())); | |
667 local_tab_pool_.AddTabNode(specifics.tab_node_id()); | 668 local_tab_pool_.AddTabNode(specifics.tab_node_id()); |
668 local_tab_pool_.AssociateTabNode(specifics.tab_node_id(), | 669 restored_tabs->push_back(*it); |
669 specifics.tab().tab_id()); | |
670 UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime()); | |
671 } | 670 } |
672 } | 671 } |
673 } | 672 } |
674 } | 673 } |
675 | 674 |
676 // Cleanup all foreign sessions, since orphaned tabs may have been added after | 675 // Cleanup all foreign sessions, since orphaned tabs may have been added after |
677 // the header. | 676 // the header. |
678 std::vector<const SyncedSession*> sessions; | 677 std::vector<const SyncedSession*> sessions; |
679 session_tracker_.LookupAllForeignSessions(&sessions, | 678 session_tracker_.LookupAllForeignSessions(&sessions, |
680 SyncedSessionTracker::RAW); | 679 SyncedSessionTracker::RAW); |
681 for (const auto* session : sessions) { | 680 for (const auto* session : sessions) { |
682 session_tracker_.CleanupSession(session->session_tag); | 681 session_tracker_.CleanupSession(session->session_tag); |
683 } | 682 } |
684 | 683 |
685 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount", | 684 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount", |
686 bad_foreign_hash_count); | 685 bad_foreign_hash_count); |
687 | 686 |
688 return found_current_header; | 687 return found_current_header; |
689 } | 688 } |
690 | 689 |
691 void SessionsSyncManager::UpdateTrackerWithSpecifics( | 690 void SessionsSyncManager::UpdateTrackerWithForeignSession( |
692 const sync_pb::SessionSpecifics& specifics, | 691 const sync_pb::SessionSpecifics& specifics, |
693 const base::Time& modification_time) { | 692 const base::Time& modification_time) { |
694 std::string session_tag = specifics.session_tag(); | 693 std::string foreign_session_tag = specifics.session_tag(); |
695 SyncedSession* session = session_tracker_.GetSession(session_tag); | 694 DCHECK_NE(foreign_session_tag, current_machine_tag()); |
| 695 |
| 696 SyncedSession* foreign_session = |
| 697 session_tracker_.GetSession(foreign_session_tag); |
696 if (specifics.has_header()) { | 698 if (specifics.has_header()) { |
697 // Read in the header data for this session. Header data is | 699 // Read in the header data for this foreign session. Header data is |
698 // essentially a collection of windows, each of which has an ordered id list | 700 // essentially a collection of windows, each of which has an ordered id list |
699 // for their tabs. | 701 // for their tabs. |
700 | 702 |
701 if (!IsValidSessionHeader(specifics.header())) { | 703 if (!IsValidSessionHeader(specifics.header())) { |
702 LOG(WARNING) << "Ignoring session node with invalid header " | 704 LOG(WARNING) << "Ignoring foreign session node with invalid header " |
703 << "and tag " << session_tag << "."; | 705 << "and tag " << foreign_session_tag << "."; |
704 return; | 706 return; |
705 } | 707 } |
706 | 708 |
707 // Load (or create) the SyncedSession object for this client. | 709 // Load (or create) the SyncedSession object for this client. |
708 const sync_pb::SessionHeader& header = specifics.header(); | 710 const sync_pb::SessionHeader& header = specifics.header(); |
709 PopulateSessionHeaderFromSpecifics(header, modification_time, session); | 711 PopulateSessionHeaderFromSpecifics(header, modification_time, |
| 712 foreign_session); |
710 | 713 |
711 // Reset the tab/window tracking for this session (must do this before | 714 // Reset the tab/window tracking for this session (must do this before |
712 // we start calling PutWindowInSession and PutTabInWindow so that all | 715 // we start calling PutWindowInSession and PutTabInWindow so that all |
713 // unused tabs/windows get cleared by the CleanupSession(...) call). | 716 // unused tabs/windows get cleared by the CleanupSession(...) call). |
714 session_tracker_.ResetSessionTracking(session_tag); | 717 session_tracker_.ResetSessionTracking(foreign_session_tag); |
715 | 718 |
716 // Process all the windows and their tab information. | 719 // Process all the windows and their tab information. |
717 int num_windows = header.window_size(); | 720 int num_windows = header.window_size(); |
718 DVLOG(1) << "Associating " << session_tag << " with " << num_windows | 721 DVLOG(1) << "Associating " << foreign_session_tag << " with " << num_windows |
719 << " windows."; | 722 << " windows."; |
720 | 723 |
721 for (int i = 0; i < num_windows; ++i) { | 724 for (int i = 0; i < num_windows; ++i) { |
722 const sync_pb::SessionWindow& window_s = header.window(i); | 725 const sync_pb::SessionWindow& window_s = header.window(i); |
723 SessionID::id_type window_id = window_s.window_id(); | 726 SessionID::id_type window_id = window_s.window_id(); |
724 session_tracker_.PutWindowInSession(session_tag, window_id); | 727 session_tracker_.PutWindowInSession(foreign_session_tag, window_id); |
725 BuildSyncedSessionFromSpecifics(session_tag, window_s, modification_time, | 728 BuildSyncedSessionFromSpecifics( |
726 session->windows[window_id].get()); | 729 foreign_session_tag, window_s, modification_time, |
| 730 foreign_session->windows[window_id].get()); |
727 } | 731 } |
728 // Delete any closed windows and unused tabs as necessary. | 732 // Delete any closed windows and unused tabs as necessary. |
729 session_tracker_.CleanupSession(session_tag); | 733 session_tracker_.CleanupSession(foreign_session_tag); |
730 } else if (specifics.has_tab()) { | 734 } else if (specifics.has_tab()) { |
731 const sync_pb::SessionTab& tab_s = specifics.tab(); | 735 const sync_pb::SessionTab& tab_s = specifics.tab(); |
732 SessionID::id_type tab_id = tab_s.tab_id(); | 736 SessionID::id_type tab_id = tab_s.tab_id(); |
733 | 737 |
734 const sessions::SessionTab* existing_tab; | 738 const sessions::SessionTab* existing_tab; |
735 if (session_tracker_.LookupSessionTab(session_tag, tab_id, &existing_tab) && | 739 if (session_tracker_.LookupSessionTab(foreign_session_tag, tab_id, |
| 740 &existing_tab) && |
736 existing_tab->timestamp > modification_time) { | 741 existing_tab->timestamp > modification_time) { |
737 // Force the tracker to remember this tab node id, even if it isn't | 742 // Force the tracker to remember this tab node id, even if it isn't |
738 // currently being used. | 743 // currently being used. |
739 session_tracker_.GetTab(session_tag, tab_id, specifics.tab_node_id()); | 744 session_tracker_.GetTab(foreign_session_tag, tab_id, |
740 DVLOG(1) << "Ignoring " << session_tag << "'s session tab " << tab_id | 745 specifics.tab_node_id()); |
741 << " with earlier modification time"; | 746 DVLOG(1) << "Ignoring " << foreign_session_tag << "'s session tab " |
| 747 << tab_id << " with earlier modification time"; |
742 return; | 748 return; |
743 } | 749 } |
744 | 750 |
745 DVLOG(1) << "Associating tab " << tab_id << " with node " | 751 sessions::SessionTab* tab = session_tracker_.GetTab( |
746 << specifics.tab_node_id(); | 752 foreign_session_tag, tab_id, specifics.tab_node_id()); |
747 sessions::SessionTab* tab = | |
748 session_tracker_.GetTab(session_tag, tab_id, specifics.tab_node_id()); | |
749 | 753 |
750 // Update SessionTab based on protobuf. | 754 // Update SessionTab based on protobuf. |
751 tab->SetFromSyncData(tab_s, modification_time); | 755 tab->SetFromSyncData(tab_s, modification_time); |
752 | 756 |
753 // If a favicon or favicon urls are present, load the URLs and visit | 757 // If a favicon or favicon urls are present, load the URLs and visit |
754 // times into the in-memory favicon cache. | 758 // times into the in-memory favicon cache. |
755 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); | 759 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); |
756 | 760 |
757 // Update the last modified time. | 761 // Update the last modified time. |
758 if (session->modified_time < modification_time) | 762 if (foreign_session->modified_time < modification_time) |
759 session->modified_time = modification_time; | 763 foreign_session->modified_time = modification_time; |
760 } else { | 764 } else { |
761 LOG(WARNING) << "Ignoring session node with missing header/tab " | 765 LOG(WARNING) << "Ignoring foreign session node with missing header/tab " |
762 << "fields and tag " << session_tag << "."; | 766 << "fields and tag " << foreign_session_tag << "."; |
763 } | 767 } |
764 } | 768 } |
765 | 769 |
766 void SessionsSyncManager::InitializeCurrentMachineTag() { | 770 void SessionsSyncManager::InitializeCurrentMachineTag() { |
767 DCHECK(current_machine_tag_.empty()); | 771 DCHECK(current_machine_tag_.empty()); |
768 std::string persisted_guid; | 772 std::string persisted_guid; |
769 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); | 773 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); |
770 if (!persisted_guid.empty()) { | 774 if (!persisted_guid.empty()) { |
771 current_machine_tag_ = persisted_guid; | 775 current_machine_tag_ = persisted_guid; |
772 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; | 776 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); | 958 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); |
955 if (success) | 959 if (success) |
956 *tab = synced_tab; | 960 *tab = synced_tab; |
957 return success; | 961 return success; |
958 } | 962 } |
959 | 963 |
960 void SessionsSyncManager::LocalTabDelegateToSpecifics( | 964 void SessionsSyncManager::LocalTabDelegateToSpecifics( |
961 const SyncedTabDelegate& tab_delegate, | 965 const SyncedTabDelegate& tab_delegate, |
962 sync_pb::SessionSpecifics* specifics) { | 966 sync_pb::SessionSpecifics* specifics) { |
963 sessions::SessionTab* session_tab = nullptr; | 967 sessions::SessionTab* session_tab = nullptr; |
964 SessionID::id_type tab_id = tab_delegate.GetSessionId(); | 968 session_tab = session_tracker_.GetTab(current_machine_tag(), |
965 session_tab = session_tracker_.GetTab(current_machine_tag(), tab_id, | 969 tab_delegate.GetSessionId(), |
966 tab_delegate.GetSyncId()); | 970 tab_delegate.GetSyncId()); |
967 SetSessionTabFromDelegate(tab_delegate, base::Time::Now(), session_tab); | 971 SetSessionTabFromDelegate(tab_delegate, base::Time::Now(), session_tab); |
968 SetVariationIds(session_tab); | 972 SetVariationIds(session_tab); |
969 sync_pb::SessionTab tab_s = session_tab->ToSyncData(); | 973 sync_pb::SessionTab tab_s = session_tab->ToSyncData(); |
970 specifics->set_session_tag(current_machine_tag_); | 974 specifics->set_session_tag(current_machine_tag_); |
971 specifics->set_tab_node_id(tab_delegate.GetSyncId()); | 975 specifics->set_tab_node_id(tab_delegate.GetSyncId()); |
972 specifics->mutable_tab()->CopyFrom(tab_s); | 976 specifics->mutable_tab()->CopyFrom(tab_s); |
973 } | 977 } |
974 | 978 |
975 void SessionsSyncManager::AssociateRestoredPlaceholderTab( | 979 void SessionsSyncManager::AssociateRestoredPlaceholderTab( |
976 const SyncedTabDelegate& tab_delegate, | 980 const SyncedTabDelegate& tab_delegate, |
977 SessionID::id_type new_tab_id, | 981 SessionID::id_type new_tab_id, |
978 SessionID::id_type new_window_id, | 982 SessionID::id_type new_window_id, |
| 983 const syncer::SyncDataList& restored_tabs, |
979 syncer::SyncChangeList* change_output) { | 984 syncer::SyncChangeList* change_output) { |
980 DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); | 985 DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); |
981 | 986 // Rewrite the tab using |restored_tabs| to retrieve the specifics. |
982 SessionID::id_type old_tab_id = | 987 if (restored_tabs.empty()) { |
983 local_tab_pool_.GetTabIdFromTabNodeId(tab_delegate.GetSyncId()); | 988 DLOG(WARNING) << "Can't Update tab ID."; |
984 DVLOG(1) << "Restoring tab id " << new_tab_id << " from sync node " | |
985 << tab_delegate.GetSyncId() << " (old tab id was " << old_tab_id | |
986 << ")."; | |
987 | |
988 // Update tab node pool and tracker with the new association (note that | |
989 // reassociating the tracker depends on the old tab pool data, so it must be | |
990 // reassociated first). | |
991 if (!session_tracker_.ReassociateTab(current_machine_tag(), old_tab_id, | |
992 new_tab_id)) { | |
993 LOG(ERROR) << "Failed to reassociate tab " << new_tab_id; | |
994 return; | 989 return; |
995 } | 990 } |
996 local_tab_pool_.ReassociateTabNode(tab_delegate.GetSyncId(), new_tab_id); | |
997 | 991 |
998 // If the tab id hasn't changed, the tab map doesn't need to be updated. But | 992 for (syncer::SyncDataList::const_iterator it = restored_tabs.begin(); |
999 // the window id may have changed, so the specifics still need to be | 993 it != restored_tabs.end(); ++it) { |
1000 // rewritten. | 994 if (it->GetSpecifics().session().tab_node_id() != |
1001 if (old_tab_id != new_tab_id) { | 995 tab_delegate.GetSyncId()) { |
1002 auto iter = local_tab_map_.find(old_tab_id); | 996 continue; |
1003 if (iter == local_tab_map_.end()) { | 997 } |
1004 LOG(ERROR) << "Failed to update local tab map for " << new_tab_id; | 998 |
| 999 sync_pb::EntitySpecifics entity; |
| 1000 sync_pb::SessionSpecifics* specifics = entity.mutable_session(); |
| 1001 specifics->CopyFrom(it->GetSpecifics().session()); |
| 1002 DCHECK(specifics->has_tab()); |
| 1003 |
| 1004 // Update tab node pool with the new association. |
| 1005 local_tab_pool_.ReassociateTabNode(tab_delegate.GetSyncId(), new_tab_id); |
| 1006 TabLink* tab_link = new TabLink(tab_delegate.GetSyncId(), &tab_delegate); |
| 1007 local_tab_map_[new_tab_id] = make_linked_ptr<TabLink>(tab_link); |
| 1008 |
| 1009 if (specifics->tab().tab_id() == new_tab_id && |
| 1010 specifics->tab().window_id() == new_window_id) |
1005 return; | 1011 return; |
1006 } | 1012 |
1007 local_tab_map_[new_tab_id] = iter->second; | 1013 // Either the tab_id or window_id changed (e.g due to session restore), so |
1008 local_tab_map_.erase(iter); | 1014 // update the sync node. |
| 1015 specifics->mutable_tab()->set_tab_id(new_tab_id); |
| 1016 specifics->mutable_tab()->set_window_id(new_window_id); |
| 1017 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 1018 TabNodePool::TabIdToTag(current_machine_tag_, specifics->tab_node_id()), |
| 1019 current_session_name_, entity); |
| 1020 change_output->push_back( |
| 1021 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); |
| 1022 return; |
1009 } | 1023 } |
1010 | |
1011 sync_pb::EntitySpecifics entity; | |
1012 sync_pb::SessionSpecifics* specifics = entity.mutable_session(); | |
1013 | |
1014 // This will rewrite the tab id and window id based on the delegate. Note | |
1015 // that it won't update the SessionWindow that holds the tab (which happens | |
1016 // separately when the header node is associated). | |
1017 LocalTabDelegateToSpecifics(tab_delegate, specifics); | |
1018 DCHECK(specifics->has_tab()); | |
1019 | |
1020 syncer::SyncData data = syncer::SyncData::CreateLocalData( | |
1021 TabNodePool::TabIdToTag(current_machine_tag_, specifics->tab_node_id()), | |
1022 current_session_name_, entity); | |
1023 change_output->push_back( | |
1024 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | |
1025 } | 1024 } |
1026 | 1025 |
1027 // static | 1026 // static |
1028 void SessionsSyncManager::SetSessionTabFromDelegate( | 1027 void SessionsSyncManager::SetSessionTabFromDelegate( |
1029 const SyncedTabDelegate& tab_delegate, | 1028 const SyncedTabDelegate& tab_delegate, |
1030 base::Time mtime, | 1029 base::Time mtime, |
1031 sessions::SessionTab* session_tab) { | 1030 sessions::SessionTab* session_tab) { |
1032 DCHECK(session_tab); | 1031 DCHECK(session_tab); |
1033 session_tab->window_id.set_id(tab_delegate.GetWindowId()); | 1032 session_tab->window_id.set_id(tab_delegate.GetWindowId()); |
1034 session_tab->tab_id.set_id(tab_delegate.GetSessionId()); | 1033 session_tab->tab_id.set_id(tab_delegate.GetSessionId()); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 } | 1132 } |
1134 | 1133 |
1135 // static | 1134 // static |
1136 std::string SessionsSyncManager::TagHashFromSpecifics( | 1135 std::string SessionsSyncManager::TagHashFromSpecifics( |
1137 const sync_pb::SessionSpecifics& specifics) { | 1136 const sync_pb::SessionSpecifics& specifics) { |
1138 return syncer::syncable::GenerateSyncableHash(syncer::SESSIONS, | 1137 return syncer::syncable::GenerateSyncableHash(syncer::SESSIONS, |
1139 TagFromSpecifics(specifics)); | 1138 TagFromSpecifics(specifics)); |
1140 } | 1139 } |
1141 | 1140 |
1142 }; // namespace sync_sessions | 1141 }; // namespace sync_sessions |
OLD | NEW |