123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/sync_sessions/sessions_global_id_mapper.h"
- #include <utility>
- #include "base/containers/contains.h"
- #include "base/containers/cxx20_erase.h"
- namespace sync_sessions {
- namespace {
- // Clean up navigation tracking when we have over this many global_ids.
- const size_t kNavigationTrackingCleanupThreshold = 100;
- // When we clean up navigation tracking, delete this many global_ids.
- const int kNavigationTrackingCleanupAmount = 10;
- } // namespace
- SessionsGlobalIdMapper::SessionsGlobalIdMapper() = default;
- SessionsGlobalIdMapper::~SessionsGlobalIdMapper() = default;
- void SessionsGlobalIdMapper::AddGlobalIdChangeObserver(
- syncer::GlobalIdChange callback) {
- global_id_change_observers_.push_back(std::move(callback));
- }
- int64_t SessionsGlobalIdMapper::GetLatestGlobalId(int64_t global_id) {
- auto g2u_iter = global_to_unique_.find(global_id);
- if (g2u_iter != global_to_unique_.end()) {
- auto u2g_iter = unique_to_current_global_.find(g2u_iter->second);
- if (u2g_iter != unique_to_current_global_.end()) {
- return u2g_iter->second;
- }
- }
- return global_id;
- }
- void SessionsGlobalIdMapper::TrackNavigationId(const base::Time& timestamp,
- int unique_id) {
- // The expectation is that global_id will update for a given unique_id, which
- // should accurately and uniquely represent a single navigation. It is
- // theoretically possible for two unique_ids to map to the same global_id, but
- // hopefully rare enough that it doesn't cause much harm. Lets record metrics
- // verify this theory.
- int64_t global_id = timestamp.ToInternalValue();
- // It is possible that the global_id has not been set yet for this navigation.
- // In this case there's nothing here for us to track yet.
- if (global_id == 0) {
- return;
- }
- DCHECK_NE(0, unique_id);
- global_to_unique_.emplace(global_id, unique_id);
- auto u2g_iter = unique_to_current_global_.find(unique_id);
- if (u2g_iter == unique_to_current_global_.end()) {
- unique_to_current_global_.insert(u2g_iter,
- std::make_pair(unique_id, global_id));
- } else if (u2g_iter->second != global_id) {
- // Remember the old_global_id before we insert and invalidate out iter.
- int64_t old_global_id = u2g_iter->second;
- // TODO(skym): Use insert_or_assign with hint once on C++17.
- unique_to_current_global_[unique_id] = global_id;
- // This should be done after updating unique_to_current_global_ in case one
- // of our observers calls into GetLatestGlobalId().
- for (auto& observer : global_id_change_observers_) {
- observer.Run(old_global_id, global_id);
- }
- }
- CleanupNavigationTracking();
- }
- void SessionsGlobalIdMapper::CleanupNavigationTracking() {
- DCHECK(kNavigationTrackingCleanupThreshold >
- kNavigationTrackingCleanupAmount);
- // |global_to_unique_| is implicitly ordered by least recently created, which
- // means we can drop from the beginning.
- if (global_to_unique_.size() > kNavigationTrackingCleanupThreshold) {
- auto iter = global_to_unique_.begin();
- std::advance(iter, kNavigationTrackingCleanupAmount);
- global_to_unique_.erase(global_to_unique_.begin(), iter);
- // While |unique_id|s do get bigger for the most part, this isn't a great
- // thing to make assumptions about, and an old tab may get refreshed often
- // and still be very important. So instead just delete anything that's
- // orphaned from |global_to_unique_|.
- base::EraseIf(unique_to_current_global_,
- [this](const std::pair<int, int64_t> kv) {
- return !base::Contains(global_to_unique_, kv.second);
- });
- }
- }
- } // namespace sync_sessions
|