chromium/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/history/history_test_utils.h"
#include "chrome/browser/lookalikes/lookalike_test_helper.h"
#include "chrome/browser/lookalikes/lookalike_url_service.h"
#include "chrome/browser/lookalikes/safety_tip_ui.h"
#include "chrome/browser/lookalikes/safety_tip_ui_helper.h"
#include "chrome/browser/lookalikes/safety_tip_web_contents_observer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/test/test_browser_dialog.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
#include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
#include "chrome/browser/ui/views/page_info/page_info_bubble_view_base.h"
#include "chrome/browser/ui/views/page_info/page_info_view_factory.h"
#include "chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/common/chrome_features.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/lookalikes/core/lookalike_url_util.h"
#include "components/lookalikes/core/safety_tip_test_utils.h"
#include "components/lookalikes/core/safety_tips.pb.h"
#include "components/lookalikes/core/safety_tips_config.h"
#include "components/page_info/core/features.h"
#include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h"
#include "components/security_interstitials/core/common_string_util.h"
#include "components/security_state/core/security_state.h"
#include "components/site_engagement/content/site_engagement_score.h"
#include "components/site_engagement/content/site_engagement_service.h"
#include "components/strings/grit/components_branded_strings.h"
#include "components/strings/grit/components_strings.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/referrer.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/url_loader_interceptor.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/common/features.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/window_open_disposition.h"
#include "ui/events/test/test_event.h"
#include "ui/gfx/range/range.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"

kInterstitialHistogramName;
NavigationSuggestionEvent;

namespace {

enum class UIStatus {};

// An engagement score above MEDIUM.
const int kHighEngagement =;

// An engagement score below MEDIUM.
const int kLowEngagement =;

const char kSafetyTipShownHistogram[] =;

// A single test case for UKM collection on triggered heuristics.
// |navigated_url| is the URL that will be navigated to.
// |expected_lookalike| is true if the navigated url is expected to trigger a
// lookalike heuristic.
struct HeuristicsTestCase {};

// Returns the full name for the give interaction histogram.
std::string GetInteractionHistogram(const char* name) {}

// Simulates a link click navigation. We don't use
// ui_test_utils::NavigateToURL(const GURL&) because it simulates the user
// typing the URL, causing the site to have a site engagement score of at
// least LOW.
//
// This function waits for safety tip checks to complete.
void NavigateToURL(Browser* browser,
                   const GURL& url,
                   WindowOpenDisposition disposition) {}

void PerformMouseClickOnView(views::View* view) {}

bool IsUIShowing() {}

void CloseWarningIgnore(views::Widget::ClosedReason reason) {}

// Sets the absolute Site Engagement |score| for the testing origin.
void SetEngagementScore(Browser* browser, const GURL& url, double score) {}

// Clicks the location icon to open the page info bubble.
void OpenPageInfoBubble(Browser* browser) {}

// Switches the tab at |tab_index| to the foreground, and waits for the
// OnVisibilityChanged safety tip check to complete.
void SwitchToTabAndWait(const Browser* browser, int tab_index) {}

// Add an allowlist with entries that aren't allowlisted for all domains.
void ConfigureAllowlistWithScopes() {}

}  // namespace

class SafetyTipPageInfoBubbleViewBrowserTest : public InProcessBrowserTest {};

// Ensure normal sites with low engagement are not blocked.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       NoShowOnLowEngagement) {}

// Ensure normal sites with low engagement are not blocked in incognito.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       NoShowOnLowEngagementIncognito) {}

// Ensure blocked sites with high engagement are not blocked.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       NoShowOnHighEngagement) {}

// Ensure blocked sites with high engagement are not blocked in incognito.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       NoShowOnHighEngagementIncognito) {}

// Ensure blocked sites get blocked.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest, ShowOnBlock) {}

// Ensure blocked sites that don't load don't get blocked.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest, NoShowOnError) {}

// Ensure blocked sites get blocked in incognito.
// TODO(crbug.com/40886576): Fix this test and re-enable.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       DISABLED_ShowOnBlockIncognito) {}

// Ensure same-document navigations don't close the Safety Tip.
// Regression test for crbug.com/1137661
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       StillShowAfterSameDocNav) {}

// Ensure sites allowed by enterprise policy don't get blocked.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       NoShowOnEnterpriseAllowlist) {}

// After the user clicks 'leave site', the user should end up on a safe domain.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       LeaveSiteLeavesSite) {}

// Test that clicking 'learn more' opens a help center article.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       LearnMoreOpensHelpCenter) {}

// If the user clicks 'leave site', the warning should re-appear when the user
// re-visits the page.
// Flaky on Mac: https://crbug.com/1139955
// Flaky in general, test depends on subtle timing, https://crbug.com/1142769
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       DISABLED_LeaveSiteStillWarnsAfter) {}

// After the user closes the warning, they should still be on the same domain.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       IgnoreWarningStaysOnPage) {}

// If the user closes the bubble, the warning should not re-appear when the user
// re-visits the page, but will still show up in PageInfo.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       IgnoreWarningStopsWarning) {}

// Non main-frame navigations should be ignored.
// TODO(meacer): This test looks incorrect, fix.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       IgnoreIFrameNavigations) {}

// Background tabs shouldn't open a bubble initially, but should when they
// become visible.
// Fails on Mac for one parameter. https://crbug.com/1285242
#if BUILDFLAG(IS_MAC)
#define MAYBE_BubbleWaitsForVisible
#else
#define MAYBE_BubbleWaitsForVisible
#endif
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       MAYBE_BubbleWaitsForVisible) {}

// Background tabs that are errors shouldn't open a tip initially, and shouldn't
// open when they become visible, either.  Test for crbug.com/1019228.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       NoBubbleOnErrorEvenAfterVisible) {}

// Tests that Safety Tips do NOT trigger on lookalike domains that trigger an
// interstitial.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       SkipLookalikeInterstitialed) {}

// Tests that Safety Tips trigger on lookalike domains that don't qualify for an
// interstitial and Page Info shows Safety Tip information.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggersOnLookalike) {}

// Tests that Safety Tips don't trigger on lookalike domains that are explicitly
// allowed by the allowlist.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       NoTriggersOnLookalikeAllowlist) {}

// Tests that Safety Tips don't trigger on lookalike domains that are explicitly
// allowed by the allowlist.
// Note: UKM is tied to the heuristic triggering, so we record no UKM here since
// the heuristic doesn't trigger. This is different from the other allowlist
// where the heuristic triggers, UKM is still recorded, but no UI is shown.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       NoTriggersOnEmbeddedAllowlist) {}

// Tests that Safety Tips trigger on lookalike domains with edit distance.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggersOnEditDistance) {}

// Tests that Safety Tips don't trigger when using a scoped allowlist.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       DoesntTriggerOnScopedAllowlist) {}

// Tests that Safety Tips trigger when the URL is on the allowlist, but is
// scoped to a different domain.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggersOnWrongScopedAllowlist) {}

// Tests that Character Swap is enabled for lookalikes matching engaged sites.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggersOnCharacterSwap_SiteEngagement) {}

// Same as TriggersOnCharacterSwap_SiteEngagement, but this time
// the match is on the actual hostnames and not skeletons. Note that
// the skeletons of example.com and éxaplme.com don't have exactly
// one character swap (exarnple.com and exaprnle.com)
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggersOnCharacterSwap_SiteEngagement_HostnameMatch) {}

// Tests that Character Swap is enabled for lookalikes matching top sites.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggersOnCharacterSwap_TopSite) {}

// Tests that a hostname on a safe TLD can spoof another hostname without a
// lookalike warning.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggersOnCharacterSwapSafeTLD_CanSpoof) {}

// Navigate to a domain within a character swap of 1 to a top domain,
// but the character swap is at the registry. This should not be flagged
// as a character swap match.
IN_PROC_BROWSER_TEST_F(
    SafetyTipPageInfoBubbleViewBrowserTest,
    DoesntTriggerOnCharacterSwap_TopSiteWithDifferentRegistry) {}

// Tests that Safety Tips trigger on lookalike domains with tail embedding when
// enabled, and not otherwise.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggersOnTailEmbedding) {}

// Tests that Safety Tips don't trigger on lookalike domains with non-tail
// target embedding.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       DoesntTriggersOnGenericTargetEmbedding) {}

// Tests that the SafetyTipShown histogram triggers correctly.
// Flaky on all platforms: https://crbug.com/1139955
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       DISABLED_SafetyTipShownHistogram) {}

// Tests that the SafetyTipIgnoredPageLoad histogram triggers correctly.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       SafetyTipIgnoredPageLoadHistogram) {}

// Tests that Safety Tip interactions are recorded in a histogram when the user
// leaves the site using the safety tip.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       InteractionsHistogram_LeaveSite) {}

// Tests that Safety Tip interactions are recorded in a histogram when the user
// dismisses the Safety Tip.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       InteractionsHistogram_DismissWithClose) {}

// Tests that Safety Tip interactions are recorded in a histogram when the user
// dismisses the Safety Tip using ESC key.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       InteractionsHistogram_DismissWithEsc) {}

// Tests that Safety Tip interactions are recorded in a histogram.
// Flaky in general: Closing the tab may or may not run the callbacks.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       DISABLED_InteractionsHistogram_CloseTab) {}

// Tests that Safety Tip interactions are recorded in a histogram when the user
// switches tabs.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       InteractionsHistogram_SwitchTab) {}

// Tests that Safety Tip interactions are recorded in a histogram when the user
// navigates away from the site.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       InteractionsHistogram_NavigateAway) {}

// Ensure that a metrics-only heuristic doesn't show up in PageInfo. Also
// a regression test for crbug/1061244.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       MetricsOnlyHeuristicDoesntShowInPageInfo) {}

// Tests that UKM data gets properly recorded when safety tip heuristics get
// triggered.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       HeuristicsUkmRecorded) {}

// Tests that UKM data is only recorded after the safety tip warning is
// dismissed or accepted, for the lookalike heuristic.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       WarningDismissalCausesUkmRecordingForLookalike) {}

// Tests that UKM data is only recorded after the safety tip warning is
// dismissed or accepted, for the blocklist heuristic.
// Flaky on all platforms: https://crbug.com/1139955
IN_PROC_BROWSER_TEST_F(
    SafetyTipPageInfoBubbleViewBrowserTest,
    DISABLED_WarningDismissalCausesUkmRecordingForBlocklist) {}

// Test that a Safety Tip is shown and metrics are recorded when
// a combo squatting url is flagged with a hard-coded brand name.
// This test case trigger `keyword` heuristic as well because of `google`
// in the URL.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggerOnComboSquatting) {}

// Test that a Safety Tip is shown and metrics are recorded when
// a combo squatting url is flagged with a hard-coded brand name.
// This test case trigger `keyword` heuristic as well because of `google`
// in the URL.
// TODO(crbug.com/40852479): keyword (embedded keyword) heuristic should
// be removed from the code including CheckHeuristicsUkmRecord.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       DontTriggerOnAllowlistedComboSquatting) {}

// Test that a Safety Tip is shown and metrics are recorded when
// a combo squatting url is flagged with a hard-coded brand name.
// In contrast with `TriggerOnComboSquatting`, this test case only
// triggers `lookalike` heuristic.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       TriggerOnlyOnComboSquatting) {}

// Test that a Safety Tip is shown and metrics are recorded when
// a combo squatting url is flagged with a brand name from engaged sites.
// In this test case, engaged site is not one of the keywords in `keyword`
// heuristic.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       ComboSquattingSiteEngagement_UIEnabled) {}

// This test checks that a Safety Tip is not shown when the UI is disabled
// via gradual rollout for Combo Squatting with hardcoded brand and keywords.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewBrowserTest,
                       ComboSquatting_UIDisabled_ShouldRecordMetrics) {}

// This test checks that a Safety Tip is not shown when the UI is disabled
// via gradual rollout for Combo Squatting with engaged sites.
IN_PROC_BROWSER_TEST_F(
    SafetyTipPageInfoBubbleViewBrowserTest,
    ComboSquattingSiteEngagement_UIDisabled_ShouldRecordMetrics) {}

class SafetyTipPageInfoBubbleViewPrerenderBrowserTest
    : public InProcessBrowserTest {};

// Tests that SafetyTipWebContentsObserver only checks heuristics when the
// primary page navigates. It loads a page in the prerenderer, verifies that
// heuristics were not run, then navigates to the prerendered site, and verifies
// that heuristics are then run.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewPrerenderBrowserTest,
                       SafetyTipOnPrerender) {}

// Ensure prerender navigations don't close the Safety Tip.
IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewPrerenderBrowserTest,
                       StillShowAfterPrerenderNavigation) {}

class SafetyTipPageInfoBubbleViewDialogTest : public DialogBrowserTest {};

IN_PROC_BROWSER_TEST_F(SafetyTipPageInfoBubbleViewDialogTest,
                       InvokeUi_Lookalike) {}