1 // Copyright 2015 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.
5 #include "components/sync_driver/revisit/offset_tab_matcher.h"
7 #include "base/metrics/histogram_macros.h"
8 #include "base/metrics/sparse_histogram.h"
9 #include "components/sessions/serialized_navigation_entry.h"
11 namespace sync_driver
{
15 // This is an upper bound of the max size of positive offset we will emit
16 // correct metrics for. Anything larger than this will be clamped to this value.
17 // This value doesn't exactly correspond to what we actually expect, this value
18 // is currently larger than expected. This value is more for the safety of our
19 // sparse histogram usage. It is assumed that the max negative offset is
20 // symmetrical and can be found by taking the negative of this value.
21 const int kMaxOffset
= 10;
25 OffsetTabMatcher::OffsetTabMatcher(const PageEquality
& page_equality
)
26 : page_equality_(page_equality
) {}
28 void OffsetTabMatcher::Check(const sessions::SessionTab
* tab
) {
29 const int current_index
= tab
->normalized_navigation_index();
30 for (std::size_t i
= 0; i
< tab
->navigations
.size(); ++i
) {
31 // Ignore the entry if it is the current entry. There's actually some
32 // ambiguity here, the index of a tab is located in two places. Hopefully
33 // they are equal, but it is possible for the index() accessor of an entry
34 // to be different from the index in the tab's vector. Theoretically this
35 // should not happen outside of tab construction logic, but to be safe all
36 // matcher logic treats the index in the vector as the authoritative index.
37 // We chose this because the other matcher wants efficient random access.
38 if (current_index
>= 0 && (std::size_t)current_index
== i
) {
41 const int offset
= i
- current_index
;
42 if (page_equality_
.IsSamePage(tab
->navigations
[i
].virtual_url()) &&
43 (best_tab_
== nullptr || best_tab_
->timestamp
< tab
->timestamp
||
44 (best_tab_
->timestamp
== tab
->timestamp
&& best_offset_
< offset
))) {
46 best_offset_
= offset
;
51 void OffsetTabMatcher::Emit(
52 const PageVisitObserver::TransitionType transition
) {
53 if (best_tab_
== nullptr) {
54 UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitNavigationMissTransition",
56 PageVisitObserver::kTransitionTypeLast
);
58 // The sparse macro allows us to handle negative offsets. However, we need
59 // to be careful when doing this because of the unrestricted nature of
60 // sparse we could end up with a very large output space across many
61 // clients. So we clamp on a resonable bound that's larger than we expect to
62 // be sure no unexpected data causes problems.
63 UMA_HISTOGRAM_SPARSE_SLOWLY("Sync.PageRevisitNavigationMatchOffset",
64 Clamp(best_offset_
, -kMaxOffset
, kMaxOffset
));
65 UMA_HISTOGRAM_CUSTOM_TIMES("Sync.PageRevisitNavigationMatchAge",
66 (base::Time::Now() - best_tab_
->timestamp
),
67 base::TimeDelta::FromSeconds(1),
68 base::TimeDelta::FromDays(14), 100);
69 UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitNavigationMatchTransition",
71 PageVisitObserver::kTransitionTypeLast
);
75 int OffsetTabMatcher::Clamp(const int input
, const int lower
, const int upper
) {
76 return std::max(lower
, std::min(upper
, input
));
79 } // namespace sync_driver