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/format_macros.h" | 10 #include "base/format_macros.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
44 const int kMaxSyncNavigationCount = 6; | 44 const int kMaxSyncNavigationCount = 6; |
45 | 45 |
46 // The URL at which the set of synced tabs is displayed. We treat it differently | 46 // The URL at which the set of synced tabs is displayed. We treat it differently |
47 // from all other URL's as accessing it triggers a sync refresh of Sessions. | 47 // from all other URL's as accessing it triggers a sync refresh of Sessions. |
48 const char kNTPOpenTabSyncURL[] = "chrome://newtab/#open_tabs"; | 48 const char kNTPOpenTabSyncURL[] = "chrome://newtab/#open_tabs"; |
49 | 49 |
50 // Default number of days without activity after which a session is considered | 50 // Default number of days without activity after which a session is considered |
51 // stale and becomes a candidate for garbage collection. | 51 // stale and becomes a candidate for garbage collection. |
52 const int kDefaultStaleSessionThresholdDays = 14; // 2 weeks. | 52 const int kDefaultStaleSessionThresholdDays = 14; // 2 weeks. |
53 | 53 |
54 // Clean up navigation tracking when we have over this many global_ids. | |
55 const size_t kNavigationTrackingCleanupThreshold = 100; | |
56 | |
57 // When we clean up navigation tracking, delete this many global_ids. | |
58 const int kNavigationTrackingCleanupAmount = 10; | |
59 | |
54 // Comparator function for use with std::sort that will sort tabs by | 60 // Comparator function for use with std::sort that will sort tabs by |
55 // descending timestamp (i.e., most recent first). | 61 // descending timestamp (i.e., most recent first). |
56 bool TabsRecencyComparator(const sessions::SessionTab* t1, | 62 bool TabsRecencyComparator(const sessions::SessionTab* t1, |
57 const sessions::SessionTab* t2) { | 63 const sessions::SessionTab* t2) { |
58 return t1->timestamp > t2->timestamp; | 64 return t1->timestamp > t2->timestamp; |
59 } | 65 } |
60 | 66 |
61 // Comparator function for use with std::sort that will sort sessions by | 67 // Comparator function for use with std::sort that will sort sessions by |
62 // descending modified_time (i.e., most recent first). | 68 // descending modified_time (i.e., most recent first). |
63 bool SessionsRecencyComparator(const SyncedSession* s1, | 69 bool SessionsRecencyComparator(const SyncedSession* s1, |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
571 GURL virtual_url = | 577 GURL virtual_url = |
572 modified_tab->GetVirtualURLAtIndex(modified_tab->GetCurrentEntryIndex()); | 578 modified_tab->GetVirtualURLAtIndex(modified_tab->GetCurrentEntryIndex()); |
573 if (virtual_url.is_valid() && | 579 if (virtual_url.is_valid() && |
574 virtual_url.spec() == kNTPOpenTabSyncURL) { | 580 virtual_url.spec() == kNTPOpenTabSyncURL) { |
575 DVLOG(1) << "Triggering sync refresh for sessions datatype."; | 581 DVLOG(1) << "Triggering sync refresh for sessions datatype."; |
576 if (!datatype_refresh_callback_.is_null()) | 582 if (!datatype_refresh_callback_.is_null()) |
577 datatype_refresh_callback_.Run(); | 583 datatype_refresh_callback_.Run(); |
578 } | 584 } |
579 } | 585 } |
580 | 586 |
587 sessions::SerializedNavigationEntry current; | |
588 modified_tab->GetSerializedNavigationAtIndex( | |
589 modified_tab->GetCurrentEntryIndex(), ¤t); | |
590 TrackNavigationIds(current); | |
591 | |
581 if (local_tab_pool_out_of_sync_) { | 592 if (local_tab_pool_out_of_sync_) { |
582 // If our tab pool is corrupt, pay the price of a full re-association to | 593 // If our tab pool is corrupt, pay the price of a full re-association to |
583 // fix things up. This takes care of the new tab modification as well. | 594 // fix things up. This takes care of the new tab modification as well. |
584 bool rebuild_association_succeeded = RebuildAssociations(); | 595 bool rebuild_association_succeeded = RebuildAssociations(); |
585 DCHECK(!rebuild_association_succeeded || !local_tab_pool_out_of_sync_); | 596 DCHECK(!rebuild_association_succeeded || !local_tab_pool_out_of_sync_); |
586 return; | 597 return; |
587 } | 598 } |
588 | 599 |
589 syncer::SyncChangeList changes; | 600 syncer::SyncChangeList changes; |
590 AssociateTab(modified_tab, &changes); | 601 AssociateTab(modified_tab, &changes); |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1278 DVLOG(1) << "Found stale session " << session_tag << " with age " | 1289 DVLOG(1) << "Found stale session " << session_tag << " with age " |
1279 << session_age_in_days << ", deleting."; | 1290 << session_age_in_days << ", deleting."; |
1280 DeleteForeignSessionInternal(session_tag, &changes); | 1291 DeleteForeignSessionInternal(session_tag, &changes); |
1281 } | 1292 } |
1282 } | 1293 } |
1283 | 1294 |
1284 if (!changes.empty()) | 1295 if (!changes.empty()) |
1285 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); | 1296 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); |
1286 } | 1297 } |
1287 | 1298 |
1299 void SessionsSyncManager::AddGlobalIdChangeObserver( | |
1300 syncer::GlobalIdChange callback) { | |
1301 global_id_change_observers_.push_back(std::move(callback)); | |
1302 } | |
1303 | |
1304 int64_t SessionsSyncManager::GetLatestGlobalId(int64_t global_id) { | |
1305 auto g2u_iter = global_to_unique_.find(global_id); | |
1306 if (g2u_iter != global_to_unique_.end()) { | |
Patrick Noland
2017/06/28 22:44:37
This might look better as if (auto g2u_iter = ...
skym
2017/07/05 19:14:28
Acknowledged.
| |
1307 auto u2g_iter = unique_to_current_global_.find(g2u_iter->second); | |
1308 if (u2g_iter != unique_to_current_global_.end()) { | |
1309 return u2g_iter->second; | |
1310 } | |
1311 } | |
1312 return global_id; | |
1313 } | |
1314 | |
1288 // static | 1315 // static |
1289 std::string SessionsSyncManager::TagHashFromSpecifics( | 1316 std::string SessionsSyncManager::TagHashFromSpecifics( |
1290 const sync_pb::SessionSpecifics& specifics) { | 1317 const sync_pb::SessionSpecifics& specifics) { |
1291 return syncer::GenerateSyncableHash(syncer::SESSIONS, | 1318 return syncer::GenerateSyncableHash(syncer::SESSIONS, |
1292 TagFromSpecifics(specifics)); | 1319 TagFromSpecifics(specifics)); |
1293 } | 1320 } |
1294 | 1321 |
1322 void SessionsSyncManager::TrackNavigationIds( | |
1323 const sessions::SerializedNavigationEntry& current) { | |
1324 // The expectation is that global_id will update for a given unique_id, which | |
1325 // should accurately and uniquely represent a single navigation. It is | |
1326 // theoretically possible for two unique_ids to map to the same global_id, but | |
1327 // hopefully rare enough that it doesn't cause much harm. Lets record metrics | |
1328 // verify this theory. | |
1329 int64_t global_id = current.timestamp().ToInternalValue(); | |
1330 // It is possible that the global_id has not been set yet for this navigation. | |
1331 // In this case there's nothing here for us to track yet. | |
1332 if (global_id == 0) { | |
1333 return; | |
1334 } | |
1335 | |
1336 int unique_id = current.unique_id(); | |
1337 DCHECK_NE(0, unique_id); | |
1338 | |
1339 auto g2u_iter = global_to_unique_.find(global_id); | |
1340 if (g2u_iter == global_to_unique_.end()) { | |
1341 global_to_unique_.insert(g2u_iter, std::make_pair(global_id, unique_id)); | |
1342 } else if (g2u_iter->second != unique_id) { | |
1343 UMA_HISTOGRAM_COUNTS("Sync.GlobalIdConflict", 1); | |
Steven Holte
2017/06/28 18:59:45
UMA_HISTOGRAM_COUNTS is an alias for UMA_HISTOGRAM
skym
2017/07/05 19:14:28
Done, switched to UMA_HISTOGRAM_ENUMERATION. Wasn'
| |
1344 } | |
1345 | |
1346 auto u2g_iter = unique_to_current_global_.find(unique_id); | |
1347 if (u2g_iter == unique_to_current_global_.end()) { | |
1348 unique_to_current_global_.insert(u2g_iter, | |
Patrick Noland
2017/06/28 22:44:37
if you use base::flat_map (see https://cs.chromium
skym
2017/07/05 19:14:28
I think it'd be a bit confusing to have these two
| |
1349 std::make_pair(unique_id, global_id)); | |
1350 } else if (u2g_iter->second != global_id) { | |
1351 // Remember the old_global_id before we insert and invalidate out iter. | |
1352 int64_t old_global_id = u2g_iter->second; | |
1353 | |
1354 // TODO(skym): Use insert_or_assign with hint once on C++17. | |
1355 unique_to_current_global_[unique_id] = global_id; | |
1356 | |
1357 // This should be done after updating unique_to_current_global_ in case one | |
1358 // of our observers calls into GetLatestGlobalId(). | |
1359 for (auto& observer : global_id_change_observers_) { | |
1360 observer.Run(old_global_id, global_id); | |
1361 } | |
1362 } | |
1363 | |
1364 CleanupNavigationTracking(); | |
1365 } | |
1366 | |
1367 void SessionsSyncManager::CleanupNavigationTracking() { | |
1368 DCHECK(kNavigationTrackingCleanupThreshold > | |
1369 kNavigationTrackingCleanupAmount); | |
1370 | |
1371 // |global_to_unique_| is implicitly ordered by least recently created, which | |
1372 // means we can drop from the beginning. | |
1373 if (global_to_unique_.size() > kNavigationTrackingCleanupThreshold) { | |
Patrick Noland
2017/06/28 22:44:37
Can you use the range-based erase here?
skym
2017/07/05 19:14:28
Done.
| |
1374 for (int i = 0; i < kNavigationTrackingCleanupAmount; ++i) { | |
1375 global_to_unique_.erase(global_to_unique_.begin()); | |
1376 } | |
1377 | |
1378 // While |unique_id|s do get bigger for the most part, this isn't a great | |
1379 // thing to make assumptions about, and an old tab may get refreshed often | |
1380 // and still be very important. So instead just delete anything that's | |
1381 // orphaned from |global_to_unique_|. | |
1382 auto u2g_iter = unique_to_current_global_.begin(); | |
1383 while (u2g_iter != unique_to_current_global_.end()) { | |
Patrick Noland
2017/06/28 22:44:37
I think you can use base::EraseIf here
skym
2017/07/05 19:14:28
Done.
| |
1384 if (global_to_unique_.find(u2g_iter->second) == global_to_unique_.end()) { | |
1385 u2g_iter = unique_to_current_global_.erase(u2g_iter); | |
1386 } else { | |
1387 ++u2g_iter; | |
1388 } | |
1389 } | |
1390 } | |
1391 } | |
1392 | |
1295 }; // namespace sync_sessions | 1393 }; // namespace sync_sessions |
OLD | NEW |