chromium/chrome/browser/ui/views/download/bubble/download_bubble_interactive_uitest.cc

// 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 "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "build/buildflag.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/download/bubble/download_bubble_prefs.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_browsertest_utils.h"
#include "chrome/browser/download/download_core_service.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/ui/accelerator_utils.h"
#include "chrome/browser/ui/browser_element_identifiers.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h"
#include "chrome/browser/ui/views/download/bubble/download_bubble_contents_view.h"
#include "chrome/browser/ui/views/download/bubble/download_toolbar_button_view.h"
#include "chrome/browser/ui/views/exclusive_access_bubble_views.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/user_education/interactive_feature_promo_test.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/test/scoped_iph_feature_list.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/safe_browsing/core/common/safe_browsing_policy_handler.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/user_education/views/help_bubble_view.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/download_test_observer.h"
#include "ui/views/widget/any_widget_observer.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/ui/chromeos/test_util.h"
#endif

#if BUILDFLAG(IS_MAC)
#include "chrome/browser/ui/browser_commands.h"
#endif

namespace {

#if !BUILDFLAG(IS_MAC)
// This waits for the download bubble widget to be shown.
views::NamedWidgetShownWaiter CreateDownloadBubbleDialogWaiter() {}

// Wait for the bubble to show up. `waiter` should be created before this
// call, and should be for the download bubble's widget name.
auto WaitForDownloadBubbleShow(views::NamedWidgetShownWaiter& waiter) {}

bool IsExclusiveAccessBubbleVisible(ExclusiveAccessBubbleViews* bubble) {}
#endif

// TODO(chlily): Deduplicate this helper class into a test utils file.
class TestDownloadManagerDelegate : public ChromeDownloadManagerDelegate {};

class DownloadBubbleInteractiveUiTest
    : public InteractiveFeaturePromoTestT<DownloadTestBase> {};

IN_PROC_BROWSER_TEST_F(DownloadBubbleInteractiveUiTest,
                       ToolbarIconAndBubbleDetailsShownAfterDownload) {}

IN_PROC_BROWSER_TEST_F(DownloadBubbleInteractiveUiTest,
                       DownloadBubbleMainView) {}

#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
IN_PROC_BROWSER_TEST_F(DownloadBubbleInteractiveUiTest,
                       DangerousDownloadShowsEsbIphPromo_WhenAutomaticClose) {
  RunTestSequence(
      Do(DownloadDangerousTestFile()),
      WaitForShow(kToolbarDownloadButtonElementId),
      Check(DownloadBubbleIsShowingDetails(IsPartialViewEnabled())),
      // Hide the partial view, if enabled. The IPH should be shown.
      Do(ChangeBubbleVisibility(false)),
      Check(DownloadBubbleIsShowingDetails(false)),
      If([&]() { return IsPartialViewEnabled(); },
         Steps(InAnyContext(WaitForShow(user_education::HelpBubbleView::
                                            kHelpBubbleElementIdForTesting)),
               Check(DownloadBubblePromoIsActive(
                   IsPartialViewEnabled(),
                   feature_engagement::kIPHDownloadEsbPromoFeature)))));
}

IN_PROC_BROWSER_TEST_F(DownloadBubbleInteractiveUiTest,
                       DangerousDownloadShowsEsbIphPromo_WhenUserClicksAway) {
  RunTestSequence(
      Do(DownloadDangerousTestFile()),
      WaitForShow(kToolbarDownloadButtonElementId),
      Check(DownloadBubbleIsShowingDetails(IsPartialViewEnabled())),
      // Click outside (at the center point of the browser) to close the bubble.
      MoveMouseTo(kBrowserViewElementId), ClickMouse(),
      EnsureNotPresent(kToolbarDownloadBubbleElementId),
      Check(DownloadBubbleIsShowingDetails(false),
            "Bubble is closed after clicking outside of it."),
      If([&]() { return IsPartialViewEnabled(); },
         Steps(InAnyContext(WaitForShow(user_education::HelpBubbleView::
                                            kHelpBubbleElementIdForTesting)),
               Check(DownloadBubblePromoIsActive(
                   IsPartialViewEnabled(),
                   feature_engagement::kIPHDownloadEsbPromoFeature)))));
}

IN_PROC_BROWSER_TEST_F(
    DownloadBubbleInteractiveUiTest,
    DangerousDownloadDoesNotShowEsbIphPromo_WhenSafeBrowsingDisabled) {
  browser()->profile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled,
                                               false);
  RunTestSequence(
      Do(DownloadDangerousTestFile()),
      WaitForShow(kToolbarDownloadButtonElementId),
      Check(DownloadBubbleIsShowingDetails(IsPartialViewEnabled())),
      // Hide the partial view, if enabled. The IPH should not be shown.
      Do(ChangeBubbleVisibility(false)),
      Check(DownloadBubbleIsShowingDetails(false)),
      Check(DownloadBubblePromoIsActive(
          false, feature_engagement::kIPHDownloadEsbPromoFeature)));
}

IN_PROC_BROWSER_TEST_F(
    DownloadBubbleInteractiveUiTest,
    DangerousDownloadDoesNotShowEsbIphPromo_WhenEnhancedSafeBrowsingEnabled) {
  browser()->profile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnhanced,
                                               true);
  RunTestSequence(
      Do(DownloadDangerousTestFile()),
      WaitForShow(kToolbarDownloadButtonElementId),
      Check(DownloadBubbleIsShowingDetails(IsPartialViewEnabled())),
      // Hide the partial view, if enabled. The IPH should not be shown.
      Do(ChangeBubbleVisibility(false)),
      Check(DownloadBubbleIsShowingDetails(false)),
      Check(DownloadBubblePromoIsActive(
          false, feature_engagement::kIPHDownloadEsbPromoFeature)));
}

IN_PROC_BROWSER_TEST_F(
    DownloadBubbleInteractiveUiTest,
    DangerousDownloadDoesNotShowEsbIphPromo_WhenSafeBrowsingSetByPolicy) {
  policy::PolicyMap policy;
  policy.Set(
      policy::key::kSafeBrowsingProtectionLevel, policy::POLICY_LEVEL_MANDATORY,
      policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
      base::Value(static_cast<int>(safe_browsing::SafeBrowsingPolicyHandler::
                                       ProtectionLevel::kStandardProtection)),
      nullptr);
  policy_provider_.UpdateChromePolicy(policy);

  EXPECT_TRUE(safe_browsing::SafeBrowsingPolicyHandler::
                  IsSafeBrowsingProtectionLevelSetByPolicy(
                      browser()->profile()->GetPrefs()));
  RunTestSequence(
      Do(DownloadDangerousTestFile()),
      WaitForShow(kToolbarDownloadButtonElementId),
      Check(DownloadBubbleIsShowingDetails(IsPartialViewEnabled())),
      // Hide the partial view, if enabled. The IPH should not be shown.
      Do(ChangeBubbleVisibility(false)),
      Check(DownloadBubbleIsShowingDetails(false)),
      Check(DownloadBubblePromoIsActive(
          false, feature_engagement::kIPHDownloadEsbPromoFeature)));
}
#endif

// This test is only for ChromeOS and Mac where we have immersive fullscreen.
#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC)
IN_PROC_BROWSER_TEST_F(DownloadBubbleInteractiveUiTest,
                       ToolbarIconShownAfterImmersiveFullscreenDownload) {
  RunTestSequence(
      Do(EnterImmersiveFullscreen()), Check(IsInImmersiveFullscreen()),
      // No download toolbar icon should be present before the download.
      EnsureNotPresent(kToolbarDownloadButtonElementId),
      // Download a file to make the partial bubble show up, if enabled.
      Do(DownloadTestFile()),
      // This step is fine and won't be flaky on ChromeOS, because waiting for
      // the element to show includes waiting for the server to notify us that
      // we are in immersive mode.
      WaitForShow(kToolbarDownloadButtonElementId),
      Check(DownloadBubbleIsShowingDetails(IsPartialViewEnabled())),
      // Hide the bubble, if enabled, so it's not showing while tearing down the
      // test browser (which causes a crash on Mac).
      // TODO(chlily): Rewrite this test to interact with the UI instead of
      // hiding the bubble artificially, to properly test user journeys.
      Do(ChangeBubbleVisibility(false)), Do(ChangeButtonVisibility(false)),
      WaitForHide(kToolbarDownloadButtonElementId));
}
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC)

// This test is only for Lacros, where tab fullscreen is non-immersive, and
// other platforms, where fullscreen is not immersive.
// TODO(chlily): Add test coverage for Mac.
#if !BUILDFLAG(IS_MAC)
// Test that downloading a file in tab fullscreen (not browser fullscreen)
// results in an exclusive access bubble, and the partial view, if enabled, is
// displayed after the tab exits fullscreen.
IN_PROC_BROWSER_TEST_F(
    DownloadBubbleInteractiveUiTest,
    ExclusiveAccessBubbleShownForTabFullscreenDownloadThenPartialView) {}
#endif

// Tests that the partial view does not steal focus from the web contents, and
// that the partial view is still closable when clicking outside of it, and that
// the main view is focused when shown.
IN_PROC_BROWSER_TEST_F(DownloadBubbleInteractiveUiTest,
                       ClosePartialBubbleOnClick) {}

}  // namespace