Chromium Code Reviews| 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 |