| 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 |