#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/bookmarks/bookmark_merged_surface_service.h"
#include "chrome/browser/bookmarks/bookmark_merged_surface_service_factory.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/bookmarks/bookmark_test_helpers.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/external_protocol/external_protocol_handler.h"
#include "chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline_manager.h"
#include "chrome/browser/preloading/chrome_preloading.h"
#include "chrome/browser/preloading/preloading_features.h"
#include "chrome/browser/preloading/scoped_prewarm_feature_list.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tab_ui_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view_observer.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view_test_helper.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/common/bookmark_pref_names.h"
#include "components/bookmarks/test/bookmark_test_helpers.h"
#include "components/page_load_metrics/browser/navigation_handle_user_data.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/prefetch_test_util.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/network/public/cpp/features.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/test/test_event.h"
#include "ui/views/animation/ink_drop.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/test/button_test_api.h"
class BookmarkBarNavigationTestBase : public InProcessBrowserTest,
public content::WebContentsObserver {
public:
BookmarkBarNavigationTestBase()
: https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
void SetUp() override { InProcessBrowserTest::SetUp(); }
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
static constexpr base::FilePath::CharType kDocRoot[] =
FILE_PATH_LITERAL("chrome/test/data");
https_test_server_.AddDefaultHandlers(base::FilePath(kDocRoot));
https_test_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
host_resolver()->AddRule("*", "127.0.0.1");
browser()->profile()->GetPrefs()->SetBoolean(
bookmarks::prefs::kShowBookmarkBar, true);
test_helper_ = std::make_unique<BookmarkBarViewTestHelper>(bookmark_bar());
Observe(web_contents());
}
void StartServers() {
ASSERT_TRUE(http_test_server_.Start());
ASSERT_TRUE(https_test_server_.Start());
}
views::LabelButton* GetBookmarkButton(size_t index) {
return test_helper_->GetBookmarkButton(index);
}
views::LabelButton* GetAppsPageShortCut() {
return test_helper_->apps_page_shortcut();
}
BrowserView* browser_view() {
return BrowserView::GetBrowserViewForBrowser(browser());
}
content::WebContents* web_contents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
BookmarkBarView* bookmark_bar() { return browser_view()->bookmark_bar(); }
std::string GetContent() {
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
return content::EvalJs(web_contents, "document.body.textContent")
.ExtractString();
}
void CreateBookmarkForHeader(const std::string& header) {
WaitForBookmarkMergedSurfaceServiceToLoad(
BookmarkMergedSurfaceServiceFactory::GetForProfile(
browser()->profile()));
bookmarks::BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(browser()->profile());
model->DisableWritesToDiskForTest();
std::string url = "/echoheader?";
model->AddURL(model->bookmark_bar_node(), 0, u"Example",
https_test_server_.GetURL(url + header));
RunScheduledLayouts();
}
void NavigateToBookmark() {
content::TestNavigationObserver observer(web_contents(), 1);
views::LabelButton* button = GetBookmarkButton(0);
views::test::ButtonTestApi clicker(button);
ui::test::TestEvent click_event;
clicker.NotifyClick(click_event);
observer.Wait();
ASSERT_EQ(std::nullopt, observer.last_initiator_origin());
}
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override {
auto* navigation_userdata =
page_load_metrics::NavigationHandleUserData::GetForNavigationHandle(
*navigation_handle);
if (navigation_userdata) {
bookmark_navigation_list_.push_back(
navigation_userdata->navigation_type());
}
}
const std::vector<
page_load_metrics::NavigationHandleUserData::InitiatorLocation>&
bookmark_navigation_list() {
return bookmark_navigation_list_;
}
net::EmbeddedTestServer* https_test_server() { return &https_test_server_; }
net::EmbeddedTestServer* http_test_server() { return &http_test_server_; }
private:
test::ScopedPrewarmFeatureList prewarm_feature_list_{
test::ScopedPrewarmFeatureList::PrewarmState::kDisabled};
net::EmbeddedTestServer https_test_server_;
net::EmbeddedTestServer http_test_server_;
std::unique_ptr<BookmarkBarViewTestHelper> test_helper_;
base::test::ScopedFeatureList scoped_feature_list_;
std::vector<page_load_metrics::NavigationHandleUserData::InitiatorLocation>
bookmark_navigation_list_;
};
class BookmarkBarNavigationTest : public BookmarkBarNavigationTestBase {
public:
void SetUpOnMainThread() override {
BookmarkBarNavigationTestBase::SetUpOnMainThread();
StartServers();
}
};
IN_PROC_BROWSER_TEST_F(BookmarkBarNavigationTest, SecFetchFromEmptyTab) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));
{
CreateBookmarkForHeader("Sec-Fetch-Dest");
NavigateToBookmark();
EXPECT_EQ("document", GetContent());
}
{
CreateBookmarkForHeader("Sec-Fetch-Mode");
NavigateToBookmark();
EXPECT_EQ("navigate", GetContent());
}
{
CreateBookmarkForHeader("Sec-Fetch-Site");
NavigateToBookmark();
EXPECT_EQ("none", GetContent());
}
{
CreateBookmarkForHeader("Sec-Fetch-User");
NavigateToBookmark();
EXPECT_EQ("?1", GetContent());
}
}
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
#define MAYBE_SecFetchSiteNoneFromNonEmptyTab \
DISABLED_SecFetchSiteNoneFromNonEmptyTab
#else
#define MAYBE_SecFetchSiteNoneFromNonEmptyTab SecFetchSiteNoneFromNonEmptyTab
#endif
IN_PROC_BROWSER_TEST_F(BookmarkBarNavigationTest,
MAYBE_SecFetchSiteNoneFromNonEmptyTab) {
ASSERT_TRUE(
ui_test_utils::NavigateToURL(browser(), GURL("http://example.com/")));
{
CreateBookmarkForHeader("Sec-Fetch-Dest");
NavigateToBookmark();
EXPECT_EQ("document", GetContent());
}
{
CreateBookmarkForHeader("Sec-Fetch-Mode");
NavigateToBookmark();
EXPECT_EQ("navigate", GetContent());
}
{
CreateBookmarkForHeader("Sec-Fetch-Site");
NavigateToBookmark();
EXPECT_EQ("none", GetContent());
}
{
CreateBookmarkForHeader("Sec-Fetch-User");
NavigateToBookmark();
EXPECT_EQ("?1", GetContent());
}
}
class FakeProtocolHandlerDelegate : public ExternalProtocolHandler::Delegate {
public:
FakeProtocolHandlerDelegate() = default;
const GURL& WaitForUrl() {
run_loop_.Run();
return url_invoked_;
}
FakeProtocolHandlerDelegate(const FakeProtocolHandlerDelegate& other) =
delete;
FakeProtocolHandlerDelegate& operator=(
const FakeProtocolHandlerDelegate& other) = delete;
class FakeDefaultSchemeClientWorker
: public shell_integration::DefaultSchemeClientWorker {
public:
explicit FakeDefaultSchemeClientWorker(const GURL& url)
: DefaultSchemeClientWorker(url) {}
FakeDefaultSchemeClientWorker(const FakeDefaultSchemeClientWorker& other) =
delete;
FakeDefaultSchemeClientWorker& operator=(
const FakeDefaultSchemeClientWorker& other) = delete;
private:
~FakeDefaultSchemeClientWorker() override = default;
shell_integration::DefaultWebClientState CheckIsDefaultImpl() override {
return shell_integration::DefaultWebClientState::NOT_DEFAULT;
}
std::u16string GetDefaultClientNameImpl() override { return u"TestApp"; }
void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, std::move(on_finished_callback));
}
};
private:
scoped_refptr<shell_integration::DefaultSchemeClientWorker> CreateShellWorker(
const GURL& url) override {
return base::MakeRefCounted<FakeDefaultSchemeClientWorker>(url);
}
void BlockRequest() override { FAIL(); }
ExternalProtocolHandler::BlockState GetBlockState(const std::string& scheme,
Profile* profile) override {
return ExternalProtocolHandler::GetBlockState(scheme, nullptr, profile);
}
void RunExternalProtocolDialog(
const GURL& url,
content::WebContents* web_contents,
ui::PageTransition page_transition,
bool has_user_gesture,
const std::optional<url::Origin>& initiating_origin,
const std::u16string& program_name) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
EXPECT_TRUE(url_invoked_.is_empty());
url_invoked_ = url;
run_loop_.Quit();
}
void LaunchUrlWithoutSecurityCheck(
const GURL& url,
content::WebContents* web_contents) override {
FAIL();
}
void FinishedProcessingCheck() override {}
GURL url_invoked_;
base::RunLoop run_loop_;
SEQUENCE_CHECKER(sequence_checker_);
};
IN_PROC_BROWSER_TEST_F(BookmarkBarNavigationTest, ExternalHandlerAllowed) {
const char external_protocol[] = "fake";
const GURL external_url = GURL("fake://path");
bookmarks::BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(browser()->profile());
bookmarks::test::WaitForBookmarkModelToLoad(model);
model->DisableWritesToDiskForTest();
model->AddURL(model->bookmark_bar_node(), 0, u"Example", external_url);
RunScheduledLayouts();
ExternalProtocolHandler::PermitLaunchUrl();
EXPECT_NE(ExternalProtocolHandler::BLOCK,
ExternalProtocolHandler::GetBlockState(external_protocol, nullptr,
browser()->profile()));
{
FakeProtocolHandlerDelegate external_handler_delegate;
ExternalProtocolHandler::SetDelegateForTesting(&external_handler_delegate);
NavigateToBookmark();
auto launched_url = external_handler_delegate.WaitForUrl();
EXPECT_EQ(external_url, launched_url);
EXPECT_EQ(ExternalProtocolHandler::BLOCK,
ExternalProtocolHandler::GetBlockState(external_protocol, nullptr,
browser()->profile()));
}
{
FakeProtocolHandlerDelegate external_handler_delegate;
ExternalProtocolHandler::SetDelegateForTesting(&external_handler_delegate);
NavigateToBookmark();
auto launched_url = external_handler_delegate.WaitForUrl();
EXPECT_EQ(external_url, launched_url);
EXPECT_EQ(ExternalProtocolHandler::BLOCK,
ExternalProtocolHandler::GetBlockState(external_protocol, nullptr,
browser()->profile()));
}
}
using UkmEntry = ukm::TestUkmRecorder::HumanReadableUkmEntry;
using ukm::builders::Preloading_Attempt;
using ukm::builders::Preloading_Prediction;
static const auto kMockElapsedTime =
base::ScopedMockElapsedTimersForTest::kMockElapsedTime;
class PreloadBookmarkBarNavigationTestBase
: public BookmarkBarNavigationTestBase {
public:
PreloadBookmarkBarNavigationTestBase()
: prerender_helper_(base::BindRepeating(
&PreloadBookmarkBarNavigationTestBase::GetActiveWebContents,
base::Unretained(this))) {}
content::WebContents* GetActiveWebContents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
void SetUpOnMainThread() override {
BookmarkBarNavigationTestBase::SetUpOnMainThread();
test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
}
ukm::TestAutoSetUkmRecorder* test_ukm_recorder() {
return test_ukm_recorder_.get();
}
void CreateBookmarkButton(GURL& preload_url) {
bookmarks::BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(browser()->profile());
bookmarks::test::WaitForBookmarkModelToLoad(model);
model->DisableWritesToDiskForTest();
model->AddURL(model->bookmark_bar_node(), 0, u"Example", preload_url);
RunScheduledLayouts();
}
void CreateBookmarkFolder() {
bookmarks::BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(browser()->profile());
bookmarks::test::WaitForBookmarkModelToLoad(model);
model->DisableWritesToDiskForTest();
model->AddFolder(model->bookmark_bar_node(), 0, u"Example");
RunScheduledLayouts();
}
void TriggerPrerenderAndNavigateToBookmarkByMousePressed(
GURL& prerender_url,
bool expect_activation) {
content::test::PrerenderHostObserver prerender_observer(
*GetActiveWebContents(), prerender_url);
views::LabelButton* button = GetBookmarkButton(0);
gfx::Point center(10, 10);
button->OnMousePressed(ui::MouseEvent(
ui::EventType::kMousePressed, center, center, ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
if (expect_activation) {
content::test::PrerenderTestHelper::WaitForPrerenderLoadCompletion(
*GetActiveWebContents(), prerender_url);
}
button->OnMouseReleased(ui::MouseEvent(
ui::EventType::kMouseReleased, center, center, ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
if (expect_activation) {
prerender_observer.WaitForActivation();
} else {
base::RunLoop().RunUntilIdle();
}
}
content::test::PrerenderTestHelper& prerender_helper() {
return prerender_helper_;
}
BookmarkBarPreloadPipelineManager* GetBookmarkBarPreloadPipelineManager() {
return browser()
->tab_strip_model()
->GetActiveTab()
->GetTabFeatures()
->bookmarkbar_preload_pipeline_manager();
}
void WaitForPrefetchCompleteOrFailed() {
base::RunLoop run_loop;
GetBookmarkBarPreloadPipelineManager()
->SetOnPrefetchCompletedOrFailedCallbackForTesting(
base::IgnoreArgs<const network::URLLoaderCompletionStatus&,
const std::optional<int>&>(
run_loop.QuitClosure()));
run_loop.Run();
}
void SimulatePrefetchFailureAndWaitForFailure(
net::test_server::ControllableHttpResponse& prefetch_response) {
base::RunLoop run_loop;
GetBookmarkBarPreloadPipelineManager()
->SetOnPrefetchCompletedOrFailedCallbackForTesting(
base::IgnoreArgs<const network::URLLoaderCompletionStatus&,
const std::optional<int>&>(
run_loop.QuitClosure()));
prefetch_response.WaitForRequest();
prefetch_response.Send(net::HTTP_INTERNAL_SERVER_ERROR);
prefetch_response.Done();
if (!run_loop.AnyQuitCalled()) {
run_loop.Run();
}
}
void TriggerPrefetchByMouseHoverOnBookmark(const GURL& prefetch_url) {
views::LabelButton* button = GetBookmarkButton(0);
gfx::Point center(10, 10);
button->OnMouseEntered(ui::MouseEvent(
ui::EventType::kMouseEntered, center, center, ui::EventTimeForNow(),
ui::EF_NONE,
ui::EF_NONE));
}
void TriggerPrefetchAndThenPrerenderAndNavigateToBookmarkByMousePressed(
GURL& preload_url,
bool expect_activation) {
TriggerPrefetchByMouseHoverOnBookmark(preload_url);
WaitForPrefetchCompleteOrFailed();
TriggerPrerenderAndNavigateToBookmarkByMousePressed(preload_url,
expect_activation);
}
private:
base::ScopedMockElapsedTimersForTest scoped_test_timer_;
content::test::PrerenderTestHelper prerender_helper_;
std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
};
constexpr int kFinalStatusActivated = 0;
constexpr int kPrerenderFailedDuringPrefetch = 86;
constexpr int kPrefetchFailedNon2XX = 12;
constexpr int kPrefetchResponseUsed = 42;
constexpr int kPreloadingTriggeringOutcomeSuccess = 5;
class PrerenderBookmarkBarOnPressedNavigationTest
: public PreloadBookmarkBarNavigationTestBase {
public:
PrerenderBookmarkBarOnPressedNavigationTest() {
std::vector<base::test::FeatureRef> enabled_features;
std::vector<base::test::FeatureRef> disabled_features;
disabled_features.push_back(features::kBookmarkTriggerForPreconnect);
disabled_features.push_back(features::kBookmarkTriggerForPrefetch);
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
const content::test::PreloadingAttemptUkmEntryBuilder& ukm_entry_builder() {
return *ukm_entry_builder_;
}
void SetUpOnMainThread() override {
PreloadBookmarkBarNavigationTestBase::SetUpOnMainThread();
StartServers();
ukm_entry_builder_ =
std::make_unique<content::test::PreloadingAttemptUkmEntryBuilder>(
chrome_preloading_predictor::kMouseHoverOrMouseDownOnBookmarkBar);
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<content::test::PreloadingAttemptUkmEntryBuilder>
ukm_entry_builder_;
};
class PrerenderBookmarkBarOnPressedNavigationTestNoTestingConfig
: public PrerenderBookmarkBarOnPressedNavigationTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
PrerenderBookmarkBarOnPressedNavigationTest::SetUpCommandLine(command_line);
command_line->AppendSwitch("disable-field-trial-config");
}
};
IN_PROC_BROWSER_TEST_F(
PrerenderBookmarkBarOnPressedNavigationTestNoTestingConfig,
PrerenderActivation) {
base::HistogramTester histogram_tester;
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), https_test_server()->GetURL("/empty.html")));
GURL prerender_url = https_test_server()->GetURL("/empty.html?prerender");
content::NavigationHandleObserver activation_observer(GetActiveWebContents(),
prerender_url);
CreateBookmarkButton(prerender_url);
TriggerPrerenderAndNavigateToBookmarkByMousePressed(prerender_url, true);
EXPECT_EQ(GetActiveWebContents()->GetLastCommittedURL(), prerender_url);
{
ukm::SourceId ukm_source_id = activation_observer.next_page_ukm_source_id();
ASSERT_TRUE(
ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
auto ukm_entries = test_ukm_recorder()->GetEntries(
Preloading_Attempt::kEntryName,
content::test::kPreloadingAttemptUkmMetrics);
EXPECT_EQ(ukm_entries.size(), 1u);
std::vector<UkmEntry> expected_entries = {
ukm_entry_builder().BuildEntry(
ukm_source_id, content::PreloadingType::kPrerender,
content::PreloadingEligibility::kEligible,
content::PreloadingHoldbackStatus::kAllowed,
content::PreloadingTriggeringOutcome::kSuccess,
content::PreloadingFailureReason::kUnspecified,
true,
kMockElapsedTime),
};
EXPECT_THAT(ukm_entries,
testing::UnorderedElementsAreArray(expected_entries))
<< content::test::ActualVsExpectedUkmEntriesToString(ukm_entries,
expected_entries);
auto entries =
test_ukm_recorder()->GetMergedEntriesByName("PrerenderPageLoad");
bool witness_bookmarkbar_ukm = false;
for (auto& kv : entries) {
const ukm::mojom::UkmEntry* entry = kv.second.get();
const ukm::UkmSource* source =
test_ukm_recorder()->GetSourceForSourceId(entry->source_id);
if (!source) {
continue;
}
EXPECT_TRUE(source->url().is_valid());
if (source->url() == prerender_url) {
test_ukm_recorder()->ExpectEntryMetric(
entry,
ukm::builders::PrerenderPageLoad::kNavigation_InitiatorLocationName,
static_cast<int>(page_load_metrics::NavigationHandleUserData::
InitiatorLocation::kBookmarkBar));
witness_bookmarkbar_ukm = true;
}
}
EXPECT_TRUE(witness_bookmarkbar_ukm);
}
histogram_tester.ExpectUniqueSample(
"Prerender.Experimental.PrerenderHostFinalStatus.Embedder_BookmarkBar",
kFinalStatusActivated, 1);
histogram_tester.ExpectUniqueSample(
"Preloading.Prerender.Attempt.MouseHoverOrMouseDownOnBookmarkBar."
"TriggeringOutcome",
kPreloadingTriggeringOutcomeSuccess, 1);
ASSERT_TRUE(
ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
ASSERT_EQ(bookmark_navigation_list().size(), 2u);
for (int i = 0; i < 2; ++i) {
EXPECT_EQ(bookmark_navigation_list()[i],
page_load_metrics::NavigationHandleUserData::InitiatorLocation::
kBookmarkBar);
}
histogram_tester.ExpectTotalCount(
"Bookmarks.BookmarkBar.PrerenderNavigationToActivation", 1);
histogram_tester.ExpectUniqueSample(
"Prerender.IsPrerenderingSRPUrl.Embedder_BookmarkBar", false, 1);
}
IN_PROC_BROWSER_TEST_F(PrerenderBookmarkBarOnPressedNavigationTest,
PrerenderNonHttps) {
base::HistogramTester histogram_tester;
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), http_test_server()->GetURL("/empty.html")));
GURL prerender_url = http_test_server()->GetURL("/empty.html?prerender");
content::NavigationHandleObserver activation_observer(GetActiveWebContents(),
prerender_url);
CreateBookmarkButton(prerender_url);
TriggerPrerenderAndNavigateToBookmarkByMousePressed(prerender_url, false);
{
ukm::SourceId ukm_source_id = activation_observer.next_page_ukm_source_id();
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), http_test_server()->GetURL("/empty.html")));
auto attempt_ukm_entries = test_ukm_recorder()->GetEntries(
Preloading_Attempt::kEntryName,
content::test::kPreloadingAttemptUkmMetrics);
EXPECT_EQ(attempt_ukm_entries.size(), 1u);
UkmEntry expected_entry = ukm_entry_builder().BuildEntry(
ukm_source_id, content::PreloadingType::kPrerender,
content::PreloadingEligibility::kHttpsOnly,
content::PreloadingHoldbackStatus::kUnspecified,
content::PreloadingTriggeringOutcome::kUnspecified,
content::PreloadingFailureReason::kUnspecified,
true);
EXPECT_EQ(attempt_ukm_entries[0], expected_entry)
<< content::test::ActualVsExpectedUkmEntryToString(
attempt_ukm_entries[0], expected_entry);
}
}
IN_PROC_BROWSER_TEST_F(PrerenderBookmarkBarOnPressedNavigationTest,
SetIsNavigationInDomainCallback) {
base::HistogramTester histogram_tester;
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), https_test_server()->GetURL("/empty.html")));
GURL prerender_url = https_test_server()->GetURL("/empty.html?prerender");
CreateBookmarkButton(prerender_url);
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), https_test_server()->GetURL("/empty.html?foo")));
views::LabelButton* button = GetBookmarkButton(0);
gfx::Point center(10, 10);
button->OnMouseEntered(ui::MouseEvent(ui::EventType::kMouseEntered, center,
center, ui::EventTimeForNow(),
ui::EF_NONE,
ui::EF_NONE));
button->OnMouseExited(ui::MouseEvent(ui::EventType::kMouseExited, center,
center, ui::EventTimeForNow(),
ui::EF_NONE,
ui::EF_NONE));
histogram_tester.ExpectBucketCount(
"Preloading.Predictor.MouseHoverOrMouseDownOnBookmarkBar.Recall",
0, 0);
histogram_tester.ExpectBucketCount(
"Preloading.Predictor.MouseHoverOrMouseDownOnBookmarkBar.Recall",
3, 0);
CreateBookmarkButton(prerender_url);
NavigateParams params(browser(),
https_test_server()->GetURL("/empty.html?bar"),
ui::PAGE_TRANSITION_AUTO_BOOKMARK);
ui_test_utils::NavigateToURL(¶ms);
histogram_tester.ExpectBucketCount(
"Preloading.Predictor.MouseHoverOrMouseDownOnBookmarkBar.Recall",
3, 1);
}
class PrerenderBookmarkBarDisabledNavigationTest
: public PreloadBookmarkBarNavigationTestBase {
public:
PrerenderBookmarkBarDisabledNavigationTest() {
scoped_feature_list_.InitAndEnableFeature(
features::kBookmarkTriggerForPrerender2KillSwitch);
}
const content::test::PreloadingAttemptUkmEntryBuilder& ukm_entry_builder() {
return *ukm_entry_builder_;
}
void SetUpOnMainThread() override {
PreloadBookmarkBarNavigationTestBase::SetUpOnMainThread();
StartServers();
ukm_entry_builder_ =
std::make_unique<content::test::PreloadingAttemptUkmEntryBuilder>(
chrome_preloading_predictor::kMouseHoverOrMouseDownOnBookmarkBar);
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<content::test::PreloadingAttemptUkmEntryBuilder>
ukm_entry_builder_;
};
IN_PROC_BROWSER_TEST_F(PrerenderBookmarkBarDisabledNavigationTest,
NonPrerenderingBookmarkBarNavigation) {
base::HistogramTester histogram_tester;
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), https_test_server()->GetURL("/empty.html")));
GURL bookmarkbar_url =
http_test_server()->GetURL("/empty.html?bookmarkbar_url");
CreateBookmarkButton(bookmarkbar_url);
NavigateToBookmark();
ASSERT_TRUE(
ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
ASSERT_EQ(bookmark_navigation_list().size(), 1u);
for (int i = 0; i < 1; ++i) {
EXPECT_EQ(bookmark_navigation_list()[i],
page_load_metrics::NavigationHandleUserData::InitiatorLocation::
kBookmarkBar);
}
histogram_tester.ExpectTotalCount(
"Bookmarks.BookmarkBar.PrerenderNavigationToActivation", 0);
}
class PreloadBookmarkBarPrefetchEnabledPrerenderEnabledNavigationTest
: public PreloadBookmarkBarNavigationTestBase {
public:
PreloadBookmarkBarPrefetchEnabledPrerenderEnabledNavigationTest() {
scoped_feature_list_.InitWithFeaturesAndParameters(
{{
features::kBookmarkTriggerForPreconnect,
{{"preconnect_start_delay_on_mouse_hover_ms", "0"}},
},
{features::kBookmarkTriggerForPrefetch,
{
{"prefetch_start_delay_on_mouse_hover_ms", "0"},
}}},
{});
}
void SetUpOnMainThread() override {
prerender_helper().RegisterServerRequestMonitor(https_test_server());
PreloadBookmarkBarNavigationTestBase::SetUpOnMainThread();
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(
PreloadBookmarkBarPrefetchEnabledPrerenderEnabledNavigationTest,
PrefetchAndPrerender) {
StartServers();
base::HistogramTester histogram_tester;
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), https_test_server()->GetURL("/empty.html")));
GURL preload_url = https_test_server()->GetURL("/empty.html?preload");
CreateBookmarkButton(preload_url);
TriggerPrefetchAndThenPrerenderAndNavigateToBookmarkByMousePressed(
preload_url, true);
EXPECT_EQ(1, prerender_helper().GetRequestCount(preload_url));
histogram_tester.ExpectUniqueSample("Preloading.Prefetch.PrefetchStatus",
kPrefetchResponseUsed, 1);
histogram_tester.ExpectUniqueSample(
"Prerender.Experimental.PrerenderHostFinalStatus.Embedder_BookmarkBar",
kFinalStatusActivated, 1);
}
IN_PROC_BROWSER_TEST_F(
PreloadBookmarkBarPrefetchEnabledPrerenderEnabledNavigationTest,
PrefetchAndPrerenderNonHttps) {
StartServers();
base::HistogramTester histogram_tester;
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), http_test_server()->GetURL("/empty.html")));
GURL preload_url = http_test_server()->GetURL("/empty.html?prerender");
content::NavigationHandleObserver activation_observer(GetActiveWebContents(),
preload_url);
CreateBookmarkButton(preload_url);
TriggerPrefetchAndThenPrerenderAndNavigateToBookmarkByMousePressed(
preload_url, false);
EXPECT_EQ(0, prerender_helper().GetRequestCount(preload_url));
histogram_tester.ExpectTotalCount(
"Prerender.Experimental.PrefetchAheadOfPrerenderFailed.PrefetchStatus."
"Embedder_BookmarkBar",
0);
histogram_tester.ExpectTotalCount(
"Prerender.Experimental.PrerenderHostFinalStatus.Embedder_BookmarkBar",
0);
}
IN_PROC_BROWSER_TEST_F(
PreloadBookmarkBarPrefetchEnabledPrerenderEnabledNavigationTest,
PrefetchFailureAndPrerenderFailure) {
net::test_server::ControllableHttpResponse prefetch_response(
https_test_server(), "/empty.html?prefetch");
StartServers();
base::HistogramTester histogram_tester;
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), https_test_server()->GetURL("/empty.html")));
GURL preload_url = https_test_server()->GetURL("/empty.html?prefetch");
content::NavigationHandleObserver activation_observer(GetActiveWebContents(),
preload_url);
CreateBookmarkButton(preload_url);
TriggerPrefetchByMouseHoverOnBookmark(preload_url);
SimulatePrefetchFailureAndWaitForFailure(prefetch_response);
TriggerPrerenderAndNavigateToBookmarkByMousePressed(preload_url, false);
histogram_tester.ExpectUniqueSample(
"Prerender.Experimental.PrefetchAheadOfPrerenderFailed.PrefetchStatus."
"Embedder_BookmarkBar",
kPrefetchFailedNon2XX, 1);
histogram_tester.ExpectUniqueSample(
"Prerender.Experimental.PrerenderHostFinalStatus.Embedder_BookmarkBar",
kPrerenderFailedDuringPrefetch, 1);
}
class BookmarkBarContextMenuTest : public PreloadBookmarkBarNavigationTestBase {
public:
void TestContextMenuHighlight(views::View* view) {
ASSERT_TRUE(!!view);
ASSERT_EQ(views::InkDropState::HIDDEN,
views::InkDrop::Get(view)->GetInkDrop()->GetTargetInkDropState());
gfx::Point point;
views::View::ConvertPointToScreen(view, &point);
bookmark_bar()->ShowContextMenuForViewImpl(
view, point, ui::mojom::MenuSourceType::kMouse);
EXPECT_EQ(views::InkDropState::ACTIVATED,
views::InkDrop::Get(view)->GetInkDrop()->GetTargetInkDropState());
bookmark_bar()->OnContextMenuClosed();
#if BUILDFLAG(IS_MAC)
EXPECT_EQ(views::InkDropState::HIDDEN,
views::InkDrop::Get(view)->GetInkDrop()->GetTargetInkDropState());
#else
EXPECT_EQ(views::InkDropState::DEACTIVATED,
views::InkDrop::Get(view)->GetInkDrop()->GetTargetInkDropState());
#endif
}
};
IN_PROC_BROWSER_TEST_F(BookmarkBarContextMenuTest,
AllBookmarksButtonHighlight) {
TestContextMenuHighlight(bookmark_bar()->all_bookmarks_button());
}
IN_PROC_BROWSER_TEST_F(BookmarkBarContextMenuTest, BookmarkButtonHighlight) {
StartServers();
GURL url = https_test_server()->GetURL("/empty.html");
CreateBookmarkButton(url);
TestContextMenuHighlight(GetBookmarkButton(0));
}
IN_PROC_BROWSER_TEST_F(BookmarkBarContextMenuTest,
BookmarkFolderButtonHighlight) {
CreateBookmarkFolder();
TestContextMenuHighlight(GetBookmarkButton(0));
}
IN_PROC_BROWSER_TEST_F(BookmarkBarContextMenuTest, AppsPageShortcutHighlight) {
TestContextMenuHighlight(GetAppsPageShortCut());
}