blob: 515543db413b21b75639f7f729b97419bdd7d81a [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chained_back_navigation_tracker.h"
#include "base/test/bind.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/navigation_simulator.h"
#include "net/dns/mock_host_resolver.h"
namespace chrome {
class ChainedBackNavigationTrackerBrowserTest : public InProcessBrowserTest {
public:
ChainedBackNavigationTrackerBrowserTest() = default;
ChainedBackNavigationTrackerBrowserTest(
const ChainedBackNavigationTrackerBrowserTest&) = delete;
ChainedBackNavigationTrackerBrowserTest& operator=(
const ChainedBackNavigationTrackerBrowserTest&) = delete;
~ChainedBackNavigationTrackerBrowserTest() override = default;
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
}
protected:
content::WebContents* web_contents() const {
return browser()->tab_strip_model()->GetActiveWebContents();
}
const uint32_t min_navigation_cnt_ =
ChainedBackNavigationTracker::kMinimumChainedBackNavigationLength;
const int64_t max_navigation_interval_ = ChainedBackNavigationTracker::
kMaxChainedBackNavigationIntervalInMilliseconds;
};
IN_PROC_BROWSER_TEST_F(ChainedBackNavigationTrackerBrowserTest,
SubframeBackNavigationIsCountedAsChained) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a1 = embedded_test_server()->GetURL("a1.com", "/title1.html");
GURL url_a2 = embedded_test_server()->GetURL("a2.com", "/title1.html");
GURL url_b = embedded_test_server()->GetURL("b.com", "/title1.html");
GURL url_c = embedded_test_server()->GetURL("c.com", "/title1.html");
ASSERT_TRUE(content::NavigateToURL(web_contents(), url_a1));
ASSERT_TRUE(content::NavigateToURL(web_contents(), url_a2));
ChainedBackNavigationTracker::CreateForWebContents(web_contents());
ChainedBackNavigationTracker* tracker =
ChainedBackNavigationTracker::FromWebContents(web_contents());
ASSERT_TRUE(tracker);
// The main frame back navigation should increment the count by 1.
ASSERT_TRUE(content::HistoryGoBack(web_contents()));
ASSERT_EQ(url_a1, web_contents()->GetLastCommittedURL());
ASSERT_EQ(1u, tracker->chained_back_navigation_count_);
// Create a subframe and append it to the document.
ASSERT_TRUE(
ExecJs(web_contents(),
content::JsReplace("let frame = document.createElement('iframe');"
"frame.src = $1;"
"document.body.appendChild(frame);",
url_b)));
ASSERT_TRUE(content::WaitForLoadStop(web_contents()));
content::RenderFrameHost* subframe_host =
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0);
// Navigate the subframe away, the chained back navigation count should be
// reset to 0.
ASSERT_TRUE(content::ExecJs(
subframe_host, content::JsReplace("window.location.href = $1;", url_c)));
ASSERT_TRUE(content::WaitForLoadStop(web_contents()));
ASSERT_EQ(0u, tracker->chained_back_navigation_count_);
// The sub frame back navigation should increment the count by 1.
ASSERT_TRUE(content::HistoryGoBack(web_contents()));
ASSERT_EQ(1u, tracker->chained_back_navigation_count_);
}
IN_PROC_BROWSER_TEST_F(ChainedBackNavigationTrackerBrowserTest,
RendererInitiatedBackNavigationIsNotCountedAsChained) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a = embedded_test_server()->GetURL("a.com", "/title1.html");
GURL url_b = embedded_test_server()->GetURL("b.com", "/title1.html");
GURL url_c = embedded_test_server()->GetURL("c.com", "/title1.html");
GURL url_d = embedded_test_server()->GetURL("d.com", "/title1.html");
ASSERT_TRUE(content::NavigateToURL(web_contents(), url_a));
ASSERT_TRUE(content::NavigateToURL(web_contents(), url_b));
ASSERT_TRUE(content::NavigateToURL(web_contents(), url_c));
ASSERT_TRUE(content::NavigateToURL(web_contents(), url_d));
ChainedBackNavigationTracker::CreateForWebContents(web_contents());
ChainedBackNavigationTracker* tracker =
ChainedBackNavigationTracker::FromWebContents(web_contents());
ASSERT_TRUE(tracker);
// No back navigation is performed yet, the chain length should not be
// updated.
ASSERT_EQ(0u, tracker->chained_back_navigation_count_);
// The back navigation is renderer initiated, it should not increment the
// chain length.
ASSERT_TRUE(content::ExecJs(web_contents(), "window.history.back();"));
ASSERT_TRUE(content::WaitForLoadStop(web_contents()));
ASSERT_EQ(url_c, web_contents()->GetLastCommittedURL());
ASSERT_EQ(0u, tracker->chained_back_navigation_count_);
// The back navigation is browser initiated, it should increment the chain
// length.
ASSERT_TRUE(content::HistoryGoBack(web_contents()));
ASSERT_EQ(url_b, web_contents()->GetLastCommittedURL());
ASSERT_EQ(1u, tracker->chained_back_navigation_count_);
// The back navigation is renderer initiated, it should reset the chain
// length.
ASSERT_TRUE(content::ExecJs(web_contents(), "window.history.back();"));
ASSERT_TRUE(content::WaitForLoadStop(web_contents()));
ASSERT_EQ(url_a, web_contents()->GetLastCommittedURL());
ASSERT_EQ(0u, tracker->chained_back_navigation_count_);
}
} // namespace chrome