Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(680)

Side by Side Diff: components/sync_sessions/sessions_sync_manager.cc

Issue 1877083002: [Sync] Moved tab_node_id tracking to session object and improved foreign session garbage collection. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixing comment for zea. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/metrics/field_trial.h" 10 #include "base/metrics/field_trial.h"
(...skipping 25 matching lines...) Expand all
36 36
37 // The maximum number of navigations in each direction we care to sync. 37 // The maximum number of navigations in each direction we care to sync.
38 const int kMaxSyncNavigationCount = 6; 38 const int kMaxSyncNavigationCount = 6;
39 39
40 // The URL at which the set of synced tabs is displayed. We treat it differently 40 // The URL at which the set of synced tabs is displayed. We treat it differently
41 // from all other URL's as accessing it triggers a sync refresh of Sessions. 41 // from all other URL's as accessing it triggers a sync refresh of Sessions.
42 const char kNTPOpenTabSyncURL[] = "chrome://newtab/#open_tabs"; 42 const char kNTPOpenTabSyncURL[] = "chrome://newtab/#open_tabs";
43 43
44 // Default number of days without activity after which a session is considered 44 // Default number of days without activity after which a session is considered
45 // stale and becomes a candidate for garbage collection. 45 // stale and becomes a candidate for garbage collection.
46 const size_t kDefaultStaleSessionThresholdDays = 14; // 2 weeks. 46 const int kDefaultStaleSessionThresholdDays = 14; // 2 weeks.
47 47
48 // Comparator function for use with std::sort that will sort tabs by 48 // Comparator function for use with std::sort that will sort tabs by
49 // descending timestamp (i.e., most recent first). 49 // descending timestamp (i.e., most recent first).
50 bool TabsRecencyComparator(const sessions::SessionTab* t1, 50 bool TabsRecencyComparator(const sessions::SessionTab* t1,
51 const sessions::SessionTab* t2) { 51 const sessions::SessionTab* t2) {
52 return t1->timestamp > t2->timestamp; 52 return t1->timestamp > t2->timestamp;
53 } 53 }
54 54
55 // Comparator function for use with std::sort that will sort sessions by 55 // Comparator function for use with std::sort that will sort sessions by
56 // descending modified_time (i.e., most recent first). 56 // descending modified_time (i.e., most recent first).
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 // to avoid any possible ping-pong delete/reassociate sequence, but 508 // to avoid any possible ping-pong delete/reassociate sequence, but
509 // remember that this happened as our TabNodePool is inconsistent. 509 // remember that this happened as our TabNodePool is inconsistent.
510 local_tab_pool_out_of_sync_ = true; 510 local_tab_pool_out_of_sync_ = true;
511 LOG(WARNING) << "Local session data deleted. Ignoring until next " 511 LOG(WARNING) << "Local session data deleted. Ignoring until next "
512 << "local navigation event."; 512 << "local navigation event.";
513 } else if (session.has_header()) { 513 } else if (session.has_header()) {
514 // Disassociate only when header node is deleted. For tab node 514 // Disassociate only when header node is deleted. For tab node
515 // deletions, the header node will be updated and foreign tab will 515 // deletions, the header node will be updated and foreign tab will
516 // get deleted. 516 // get deleted.
517 DisassociateForeignSession(session.session_tag()); 517 DisassociateForeignSession(session.session_tag());
518 } else if (session.has_tab()) {
519 // The challenge here is that we don't know if this tab deletion is
520 // being processed before or after the parent was updated to no longer
521 // references the tab. Or, even more extreme, the parent has been
522 // deleted as well. Tell the tracker to do what it can. The header's
523 // update will mostly get us into the correct state, the only thing
524 // this deletion needs to accomplish is make sure we never tell sync
525 // to delete this tab later during garbage collection.
526 session_tracker_.DeleteForeignTab(session.session_tag(),
527 session.tab_node_id());
518 } 528 }
519 break; 529 break;
520 case syncer::SyncChange::ACTION_ADD: 530 case syncer::SyncChange::ACTION_ADD:
521 case syncer::SyncChange::ACTION_UPDATE: 531 case syncer::SyncChange::ACTION_UPDATE:
522 if (current_machine_tag() == session.session_tag()) { 532 if (current_machine_tag() == session.session_tag()) {
523 // We should only ever receive a change to our own machine's session 533 // We should only ever receive a change to our own machine's session
524 // info if encryption was turned on. In that case, the data is still 534 // info if encryption was turned on. In that case, the data is still
525 // the same, so we can ignore. 535 // the same, so we can ignore.
526 // TODO(skym): Is it really safe to return here? Why not continue?
527 // Couldn't there be multiple SessionSpecifics in the SyncChangeList
528 // that contain different session tags?
529 LOG(WARNING) << "Dropping modification to local session."; 536 LOG(WARNING) << "Dropping modification to local session.";
530 return syncer::SyncError(); 537 return syncer::SyncError();
531 } 538 }
532 UpdateTrackerWithForeignSession( 539 UpdateTrackerWithForeignSession(
533 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); 540 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime());
534 break; 541 break;
535 default: 542 default:
536 NOTREACHED() << "Processing sync changes failed, unknown change type."; 543 NOTREACHED() << "Processing sync changes failed, unknown change type.";
537 } 544 }
538 } 545 }
(...skipping 12 matching lines...) Expand all
551 return syncer::SyncChange( 558 return syncer::SyncChange(
552 FROM_HERE, SyncChange::ACTION_DELETE, 559 FROM_HERE, SyncChange::ACTION_DELETE,
553 SyncData::CreateLocalDelete( 560 SyncData::CreateLocalDelete(
554 TabNodePool::TabIdToTag(current_machine_tag(), tab.tab_node_id()), 561 TabNodePool::TabIdToTag(current_machine_tag(), tab.tab_node_id()),
555 syncer::SESSIONS)); 562 syncer::SESSIONS));
556 } 563 }
557 } 564 }
558 565
559 bool SessionsSyncManager::GetAllForeignSessions( 566 bool SessionsSyncManager::GetAllForeignSessions(
560 std::vector<const sync_driver::SyncedSession*>* sessions) { 567 std::vector<const sync_driver::SyncedSession*>* sessions) {
561 if (!session_tracker_.LookupAllForeignSessions(sessions)) 568 if (!session_tracker_.LookupAllForeignSessions(
569 sessions, SyncedSessionTracker::PRESENTABLE))
562 return false; 570 return false;
563 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); 571 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator);
564 return true; 572 return true;
565 } 573 }
566 574
567 bool SessionsSyncManager::InitFromSyncModel( 575 bool SessionsSyncManager::InitFromSyncModel(
568 const syncer::SyncDataList& sync_data, 576 const syncer::SyncDataList& sync_data,
569 syncer::SyncDataList* restored_tabs, 577 syncer::SyncDataList* restored_tabs,
570 syncer::SyncChangeList* new_changes) { 578 syncer::SyncChangeList* new_changes) {
571 bool found_current_header = false; 579 bool found_current_header = false;
572 for (syncer::SyncDataList::const_iterator it = sync_data.begin(); 580 for (syncer::SyncDataList::const_iterator it = sync_data.begin();
573 it != sync_data.end(); ++it) { 581 it != sync_data.end(); ++it) {
574 // TODO(skym): Why don't we ever look at data.change_type()? Why is this
575 // code path so much different from ProcessSyncChanges?
576 const syncer::SyncData& data = *it; 582 const syncer::SyncData& data = *it;
577 DCHECK(data.GetSpecifics().has_session()); 583 DCHECK(data.GetSpecifics().has_session());
578 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); 584 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session();
579 if (specifics.session_tag().empty() || 585 if (specifics.session_tag().empty() ||
580 (specifics.has_tab() && 586 (specifics.has_tab() &&
581 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { 587 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) {
582 syncer::SyncChange tombstone(TombstoneTab(specifics)); 588 syncer::SyncChange tombstone(TombstoneTab(specifics));
583 if (tombstone.IsValid()) 589 if (tombstone.IsValid())
584 new_changes->push_back(tombstone); 590 new_changes->push_back(tombstone);
585 } else if (specifics.session_tag() != current_machine_tag()) { 591 } else if (specifics.session_tag() != current_machine_tag()) {
(...skipping 15 matching lines...) Expand all
601 new_changes->push_back(tombstone); 607 new_changes->push_back(tombstone);
602 } else { 608 } else {
603 // This is a valid old tab node, add it to the pool so it can be 609 // This is a valid old tab node, add it to the pool so it can be
604 // reused for reassociation. 610 // reused for reassociation.
605 local_tab_pool_.AddTabNode(specifics.tab_node_id()); 611 local_tab_pool_.AddTabNode(specifics.tab_node_id());
606 restored_tabs->push_back(*it); 612 restored_tabs->push_back(*it);
607 } 613 }
608 } 614 }
609 } 615 }
610 } 616 }
617
618 // Cleanup all foreign sessions, since orphaned tabs may have been added after
619 // the header.
620 std::vector<const sync_driver::SyncedSession*> sessions;
621 session_tracker_.LookupAllForeignSessions(&sessions,
622 SyncedSessionTracker::RAW);
623 for (const auto* session : sessions) {
624 session_tracker_.CleanupSession(session->session_tag);
625 }
626
611 return found_current_header; 627 return found_current_header;
612 } 628 }
613 629
614 void SessionsSyncManager::UpdateTrackerWithForeignSession( 630 void SessionsSyncManager::UpdateTrackerWithForeignSession(
615 const sync_pb::SessionSpecifics& specifics, 631 const sync_pb::SessionSpecifics& specifics,
616 const base::Time& modification_time) { 632 const base::Time& modification_time) {
617 std::string foreign_session_tag = specifics.session_tag(); 633 std::string foreign_session_tag = specifics.session_tag();
618 DCHECK_NE(foreign_session_tag, current_machine_tag()); 634 DCHECK_NE(foreign_session_tag, current_machine_tag());
619 635
620 sync_driver::SyncedSession* foreign_session = 636 sync_driver::SyncedSession* foreign_session =
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 // Delete any closed windows and unused tabs as necessary. 672 // Delete any closed windows and unused tabs as necessary.
657 session_tracker_.CleanupSession(foreign_session_tag); 673 session_tracker_.CleanupSession(foreign_session_tag);
658 } else if (specifics.has_tab()) { 674 } else if (specifics.has_tab()) {
659 const sync_pb::SessionTab& tab_s = specifics.tab(); 675 const sync_pb::SessionTab& tab_s = specifics.tab();
660 SessionID::id_type tab_id = tab_s.tab_id(); 676 SessionID::id_type tab_id = tab_s.tab_id();
661 677
662 const sessions::SessionTab* existing_tab; 678 const sessions::SessionTab* existing_tab;
663 if (session_tracker_.LookupSessionTab(foreign_session_tag, tab_id, 679 if (session_tracker_.LookupSessionTab(foreign_session_tag, tab_id,
664 &existing_tab) && 680 &existing_tab) &&
665 existing_tab->timestamp > modification_time) { 681 existing_tab->timestamp > modification_time) {
682 // Force the tracker to remember this tab node id, even if it isn't
683 // currently being used.
684 session_tracker_.GetTab(foreign_session_tag, tab_id,
685 specifics.tab_node_id());
666 DVLOG(1) << "Ignoring " << foreign_session_tag << "'s session tab " 686 DVLOG(1) << "Ignoring " << foreign_session_tag << "'s session tab "
667 << tab_id << " with earlier modification time"; 687 << tab_id << " with earlier modification time";
668 return; 688 return;
669 } 689 }
670 690
671 sessions::SessionTab* tab = session_tracker_.GetTab( 691 sessions::SessionTab* tab = session_tracker_.GetTab(
672 foreign_session_tag, tab_id, specifics.tab_node_id()); 692 foreign_session_tag, tab_id, specifics.tab_node_id());
673 693
674 // Update SessionTab based on protobuf. 694 // Update SessionTab based on protobuf.
675 tab->SetFromSyncData(tab_s, modification_time); 695 tab->SetFromSyncData(tab_s, modification_time);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 case sync_pb::SyncEnums_DeviceType_TYPE_TABLET: 753 case sync_pb::SyncEnums_DeviceType_TYPE_TABLET:
734 session_header->device_type = sync_driver::SyncedSession::TYPE_TABLET; 754 session_header->device_type = sync_driver::SyncedSession::TYPE_TABLET;
735 break; 755 break;
736 case sync_pb::SyncEnums_DeviceType_TYPE_OTHER: 756 case sync_pb::SyncEnums_DeviceType_TYPE_OTHER:
737 // Intentionally fall-through 757 // Intentionally fall-through
738 default: 758 default:
739 session_header->device_type = sync_driver::SyncedSession::TYPE_OTHER; 759 session_header->device_type = sync_driver::SyncedSession::TYPE_OTHER;
740 break; 760 break;
741 } 761 }
742 } 762 }
743 session_header->modified_time = mtime; 763 session_header->modified_time =
764 std::max(mtime, session_header->modified_time);
744 } 765 }
745 766
746 // static 767 // static
747 void SessionsSyncManager::BuildSyncedSessionFromSpecifics( 768 void SessionsSyncManager::BuildSyncedSessionFromSpecifics(
748 const std::string& session_tag, 769 const std::string& session_tag,
749 const sync_pb::SessionWindow& specifics, 770 const sync_pb::SessionWindow& specifics,
750 base::Time mtime, 771 base::Time mtime,
751 sessions::SessionWindow* session_window) { 772 sessions::SessionWindow* session_window) {
752 if (specifics.has_window_id()) 773 if (specifics.has_window_id())
753 session_window->window_id.set_id(specifics.window_id()); 774 session_window->window_id.set_id(specifics.window_id());
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 const std::string& tag, 825 const std::string& tag,
805 syncer::SyncChangeList* change_output) { 826 syncer::SyncChangeList* change_output) {
806 if (tag == current_machine_tag()) { 827 if (tag == current_machine_tag()) {
807 LOG(ERROR) << "Attempting to delete local session. This is not currently " 828 LOG(ERROR) << "Attempting to delete local session. This is not currently "
808 << "supported."; 829 << "supported.";
809 return; 830 return;
810 } 831 }
811 832
812 std::set<int> tab_node_ids_to_delete; 833 std::set<int> tab_node_ids_to_delete;
813 session_tracker_.LookupTabNodeIds(tag, &tab_node_ids_to_delete); 834 session_tracker_.LookupTabNodeIds(tag, &tab_node_ids_to_delete);
814 if (!DisassociateForeignSession(tag)) { 835 if (DisassociateForeignSession(tag)) {
815 // We don't have any data for this session, our work here is done! 836 // Only tell sync to delete the header if there was one.
816 return; 837 change_output->push_back(
838 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE,
839 SyncData::CreateLocalDelete(tag, syncer::SESSIONS)));
817 } 840 }
818
819 // Prepare deletes for the meta-node as well as individual tab nodes.
820 change_output->push_back(
821 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE,
822 SyncData::CreateLocalDelete(tag, syncer::SESSIONS)));
823
824 for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin(); 841 for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin();
825 it != tab_node_ids_to_delete.end(); ++it) { 842 it != tab_node_ids_to_delete.end(); ++it) {
826 change_output->push_back(syncer::SyncChange( 843 change_output->push_back(syncer::SyncChange(
827 FROM_HERE, SyncChange::ACTION_DELETE, 844 FROM_HERE, SyncChange::ACTION_DELETE,
828 SyncData::CreateLocalDelete(TabNodePool::TabIdToTag(tag, *it), 845 SyncData::CreateLocalDelete(TabNodePool::TabIdToTag(tag, *it),
829 syncer::SESSIONS))); 846 syncer::SESSIONS)));
830 } 847 }
831 if (!sessions_updated_callback_.is_null()) 848 if (!sessions_updated_callback_.is_null())
832 sessions_updated_callback_.Run(); 849 sessions_updated_callback_.Run();
833 } 850 }
834 851
835 bool SessionsSyncManager::DisassociateForeignSession( 852 bool SessionsSyncManager::DisassociateForeignSession(
836 const std::string& foreign_session_tag) { 853 const std::string& foreign_session_tag) {
837 if (foreign_session_tag == current_machine_tag()) { 854 DCHECK_NE(foreign_session_tag, current_machine_tag());
838 DVLOG(1) << "Local session deleted! Doing nothing until a navigation is "
839 << "triggered.";
840 return false;
841 }
842 DVLOG(1) << "Disassociating session " << foreign_session_tag; 855 DVLOG(1) << "Disassociating session " << foreign_session_tag;
843 return session_tracker_.DeleteSession(foreign_session_tag); 856 return session_tracker_.DeleteSession(foreign_session_tag);
844 } 857 }
845 858
846 bool SessionsSyncManager::GetForeignSession( 859 bool SessionsSyncManager::GetForeignSession(
847 const std::string& tag, 860 const std::string& tag,
848 std::vector<const sessions::SessionWindow*>* windows) { 861 std::vector<const sessions::SessionWindow*>* windows) {
849 return session_tracker_.LookupSessionWindows(tag, windows); 862 return session_tracker_.LookupSessionWindows(tag, windows);
850 } 863 }
851 864
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 return &favicon_cache_; 1036 return &favicon_cache_;
1024 } 1037 }
1025 1038
1026 SyncedWindowDelegatesGetter* 1039 SyncedWindowDelegatesGetter*
1027 SessionsSyncManager::synced_window_delegates_getter() const { 1040 SessionsSyncManager::synced_window_delegates_getter() const {
1028 return sessions_client_->GetSyncedWindowDelegatesGetter(); 1041 return sessions_client_->GetSyncedWindowDelegatesGetter();
1029 } 1042 }
1030 1043
1031 void SessionsSyncManager::DoGarbageCollection() { 1044 void SessionsSyncManager::DoGarbageCollection() {
1032 std::vector<const sync_driver::SyncedSession*> sessions; 1045 std::vector<const sync_driver::SyncedSession*> sessions;
1033 if (!GetAllForeignSessions(&sessions)) 1046 if (!session_tracker_.LookupAllForeignSessions(&sessions,
1047 SyncedSessionTracker::RAW))
1034 return; // No foreign sessions. 1048 return; // No foreign sessions.
1035 1049
1036 // Iterate through all the sessions and delete any with age older than 1050 // Iterate through all the sessions and delete any with age older than
1037 // |stale_session_threshold_days_|. 1051 // |stale_session_threshold_days_|.
1038 syncer::SyncChangeList changes; 1052 syncer::SyncChangeList changes;
1039 for (std::vector<const sync_driver::SyncedSession*>::const_iterator iter = 1053 for (const auto* session : sessions) {
1040 sessions.begin();
1041 iter != sessions.end(); ++iter) {
1042 const sync_driver::SyncedSession* session = *iter;
1043 int session_age_in_days = 1054 int session_age_in_days =
1044 (base::Time::Now() - session->modified_time).InDays(); 1055 (base::Time::Now() - session->modified_time).InDays();
1045 std::string session_tag = session->session_tag; 1056 if (session_age_in_days > stale_session_threshold_days_) {
1046 if (session_age_in_days > 0 && // If false, local clock is not trustworty. 1057 std::string session_tag = session->session_tag;
1047 static_cast<size_t>(session_age_in_days) >
1048 stale_session_threshold_days_) {
1049 DVLOG(1) << "Found stale session " << session_tag << " with age " 1058 DVLOG(1) << "Found stale session " << session_tag << " with age "
1050 << session_age_in_days << ", deleting."; 1059 << session_age_in_days << ", deleting.";
1051 DeleteForeignSessionInternal(session_tag, &changes); 1060 DeleteForeignSessionInternal(session_tag, &changes);
1052 } 1061 }
1053 } 1062 }
1054 1063
1055 if (!changes.empty()) 1064 if (!changes.empty())
1056 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); 1065 sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
1057 } 1066 }
1058 1067
1059 }; // namespace browser_sync 1068 }; // namespace browser_sync
OLDNEW
« no previous file with comments | « components/sync_sessions/sessions_sync_manager.h ('k') | components/sync_sessions/synced_session.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698