1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chained_back_navigation_tracker.h"
7 #include "base/test/bind.h"
8 #include "base/test/task_environment.h"
9 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
10 #include "content/public/browser/web_contents.h"
11 #include "content/public/test/browser_test_utils.h"
12 #include "content/public/test/navigation_simulator.h"
16 class ChainedBackNavigationTrackerTest
17 : public ChromeRenderViewHostTestHarness {
19 ChainedBackNavigationTrackerTest()
20 : ChromeRenderViewHostTestHarness(
21 base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
24 const uint32_t min_navigation_cnt_ =
25 ChainedBackNavigationTracker::kMinimumChainedBackNavigationLength;
26 const int64_t max_navigation_interval_ = ChainedBackNavigationTracker::
27 kMaxChainedBackNavigationIntervalInMilliseconds;
30 TEST_F(ChainedBackNavigationTrackerTest, ChainedBackNavigationStatus) {
31 std::vector<const GURL> urls;
32 for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) {
33 urls.push_back(GURL("http://foo/" + base::NumberToString(i)));
35 for (const GURL& url : urls) {
36 NavigateAndCommit(url);
39 ChainedBackNavigationTracker::CreateForWebContents(web_contents());
40 const ChainedBackNavigationTracker* tracker =
41 ChainedBackNavigationTracker::FromWebContents(web_contents());
44 // Before any back navigation, the return value for these two checker
45 // functions should be false.
46 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
47 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
49 for (uint32_t i = 1; i < urls.size(); ++i) {
50 content::NavigationSimulator::GoBack(web_contents());
51 // Since `RecordBackButtonClickForChainedBackNavigation()` is never called,
52 // `IsBackButtonChainedBackNavigationRecentlyPerformed()` should always
54 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
55 // The check should only return true when the number of consecutive back
56 // navigation is smaller than `kMinimumChainedBackNavigationLength`.
57 if (i < min_navigation_cnt_) {
58 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
60 ASSERT_TRUE(tracker->IsChainedBackNavigationRecentlyPerformed());
65 TEST_F(ChainedBackNavigationTrackerTest,
66 ChainedBackNavigationStatus_ResetCountIfIntervalIsTooLong) {
67 std::vector<const GURL> urls;
68 for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) {
69 urls.push_back(GURL("http://foo/" + base::NumberToString(i)));
71 for (const GURL& url : urls) {
72 NavigateAndCommit(url);
75 ChainedBackNavigationTracker::CreateForWebContents(web_contents());
76 const ChainedBackNavigationTracker* tracker =
77 ChainedBackNavigationTracker::FromWebContents(web_contents());
80 // Before any back navigation, the return value for these two checker
81 // functions should be false.
82 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
83 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
85 for (uint32_t i = 1; i < min_navigation_cnt_; ++i) {
86 content::NavigationSimulator::GoBack(web_contents());
87 // The checks should always return false since the number of consecutive
88 // back navigation is smaller than `kMinimumChainedBackNavigationLength`.
89 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
90 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
93 // After waiting for sufficiently long interval, the counter should be reset
94 // so the checks should always return false.
95 task_environment()->FastForwardBy(
96 base::Milliseconds(max_navigation_interval_ * 2));
97 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
98 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
100 for (uint32_t i = 1; i < min_navigation_cnt_; ++i) {
101 content::NavigationSimulator::GoBack(web_contents());
102 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
103 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
108 ChainedBackNavigationTrackerTest,
109 ChainedBackNavigationStatus_ResetCountIfNonBackForwardNavigationHappens) {
110 std::vector<const GURL> urls;
111 for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) {
112 urls.push_back(GURL("http://foo/" + base::NumberToString(i)));
114 for (const GURL& url : urls) {
115 NavigateAndCommit(url);
118 ChainedBackNavigationTracker::CreateForWebContents(web_contents());
119 const ChainedBackNavigationTracker* tracker =
120 ChainedBackNavigationTracker::FromWebContents(web_contents());
121 ASSERT_TRUE(tracker);
123 // Before any back navigation, the return value for these two checker
124 // functions should be false.
125 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
126 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
128 for (uint32_t i = 1; i < min_navigation_cnt_; ++i) {
129 content::NavigationSimulator::GoBack(web_contents());
130 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
131 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
134 // After performing another non history navigation, the counter should be
135 // reset so the checks should always return false.
136 NavigateAndCommit(GURL("http://bar/1"));
137 ASSERT_EQ(0u, tracker->chained_back_navigation_count_);
139 for (uint32_t i = 1; i < min_navigation_cnt_; ++i) {
140 content::NavigationSimulator::GoBack(web_contents());
141 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
142 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
146 TEST_F(ChainedBackNavigationTrackerTest,
147 ChainedBackNavigationStatus_BackButtonClicked) {
148 std::vector<const GURL> urls;
149 for (uint32_t i = 0; i < min_navigation_cnt_ * 2; ++i) {
150 urls.push_back(GURL("http://foo/" + base::NumberToString(i)));
152 for (const GURL& url : urls) {
153 NavigateAndCommit(url);
156 ChainedBackNavigationTracker::CreateForWebContents(web_contents());
157 ChainedBackNavigationTracker* tracker =
158 ChainedBackNavigationTracker::FromWebContents(web_contents());
159 ASSERT_TRUE(tracker);
161 // Before any back navigation, the return value for these two checker
162 // functions should be false.
163 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
164 ASSERT_FALSE(tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
166 for (uint32_t i = 1; i < urls.size(); ++i) {
167 tracker->RecordBackButtonClickForChainedBackNavigation();
168 content::NavigationSimulator::GoBack(web_contents());
169 // The checks should only return true when the number of consecutive back
170 // navigation is greater than or equal to
171 // `kMinimumChainedBackNavigationLength`.
172 if (i >= min_navigation_cnt_) {
173 ASSERT_TRUE(tracker->IsChainedBackNavigationRecentlyPerformed());
175 tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
177 ASSERT_FALSE(tracker->IsChainedBackNavigationRecentlyPerformed());
179 tracker->IsBackButtonChainedBackNavigationRecentlyPerformed());
184 } // namespace chrome