similar_visit_deduper_cluster_finalizer.cc 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/history_clusters/core/similar_visit_deduper_cluster_finalizer.h"
  5. #include "base/ranges/algorithm.h"
  6. #include "components/history/core/browser/history_types.h"
  7. #include "components/history_clusters/core/on_device_clustering_util.h"
  8. namespace history_clusters {
  9. namespace {
  10. struct SimilarVisit {
  11. SimilarVisit() = default;
  12. explicit SimilarVisit(const history::ClusterVisit& visit)
  13. : title(visit.annotated_visit.url_row.title()),
  14. url_for_deduping(visit.url_for_deduping) {}
  15. SimilarVisit(const SimilarVisit&) = default;
  16. ~SimilarVisit() = default;
  17. std::u16string title;
  18. GURL url_for_deduping;
  19. struct Comp {
  20. bool operator()(const SimilarVisit& lhs, const SimilarVisit& rhs) const {
  21. if (lhs.title != rhs.title)
  22. return lhs.title < rhs.title;
  23. return lhs.url_for_deduping < rhs.url_for_deduping;
  24. }
  25. };
  26. };
  27. } // namespace
  28. SimilarVisitDeduperClusterFinalizer::SimilarVisitDeduperClusterFinalizer() =
  29. default;
  30. SimilarVisitDeduperClusterFinalizer::~SimilarVisitDeduperClusterFinalizer() =
  31. default;
  32. void SimilarVisitDeduperClusterFinalizer::FinalizeCluster(
  33. history::Cluster& cluster) {
  34. base::flat_map<SimilarVisit, history::ClusterVisit*, SimilarVisit::Comp>
  35. similar_visit_to_canonical_visits;
  36. // First do a prepass to find the canonical visit for each SimilarVisit key.
  37. // This simply marks the last visit in `cluster` with any given SimilarVisit
  38. // key as the canonical one.
  39. for (auto& visit : cluster.visits) {
  40. similar_visit_to_canonical_visits[SimilarVisit(visit)] = &visit;
  41. }
  42. cluster.visits.erase(
  43. base::ranges::remove_if(
  44. cluster.visits,
  45. [&](auto& visit) {
  46. // We are guaranteed to find a matching canonical visit, due to our
  47. // prepass above.
  48. auto it =
  49. similar_visit_to_canonical_visits.find(SimilarVisit(visit));
  50. DCHECK(it != similar_visit_to_canonical_visits.end());
  51. history::ClusterVisit* canonical_visit = it->second;
  52. // If a DIFFERENT visit is the canonical visit for this key, merge
  53. // this visit in, and mark this visit as to be removed.
  54. if (&visit != canonical_visit) {
  55. MergeDuplicateVisitIntoCanonicalVisit(std::move(visit),
  56. *canonical_visit);
  57. return true;
  58. }
  59. return false;
  60. }),
  61. cluster.visits.end());
  62. }
  63. } // namespace history_clusters