chromium/chrome/browser/chrome_for_testing/chrome_for_testing_info_bar_browsertest.cc

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

#include <memory>
#include <utility>

#include "chrome/browser/infobars/confirm_infobar_creator.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/infobars/core/confirm_infobar_delegate.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_delegate.h"
#include "components/infobars/core/infobars_switches.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace infobars {

namespace {

class ChromeForTestingInfoBarTest : public InProcessBrowserTest {
 public:
  ChromeForTestingInfoBarTest() = default;
  ~ChromeForTestingInfoBarTest() override = default;

  ChromeForTestingInfoBarTest(const ChromeForTestingInfoBarTest&) = delete;
  ChromeForTestingInfoBarTest& operator=(const ChromeForTestingInfoBarTest&) =
      delete;

 protected:
  content::WebContents* GetActiveWebContents() {
    return browser()->tab_strip_model()->GetActiveWebContents();
  }

  ContentInfoBarManager* GetActiveWebContentsInfoBarManager() {
    return ContentInfoBarManager::FromWebContents(GetActiveWebContents());
  }

  ContentInfoBarManager* GetInfoBarManagerFromTabIndex(int tab_index) {
    return ContentInfoBarManager::FromWebContents(
        browser()->tab_strip_model()->GetWebContentsAt(tab_index));
  }
};

IN_PROC_BROWSER_TEST_F(ChromeForTestingInfoBarTest, InfoBarAppears) {
  ContentInfoBarManager* infobar_manager = GetInfoBarManagerFromTabIndex(0);

  // Verify that the info bar is shown.
  ASSERT_EQ(1u, infobar_manager->infobars().size());

  auto* test_infobar = infobar_manager->infobars()[0]->delegate();

  // Assert that it is the Chrome for Testing info bar.
  ASSERT_EQ(ConfirmInfoBarDelegate::InfoBarIdentifier::
                CHROME_FOR_TESTING_INFOBAR_DELEGATE,
            test_infobar->GetIdentifier());

  EXPECT_FALSE(test_infobar->IsCloseable());
  EXPECT_FALSE(test_infobar->ShouldAnimate());
}

IN_PROC_BROWSER_TEST_F(ChromeForTestingInfoBarTest, InfoBarAppearsInEveryTab) {
  // Open a second tab in the same window.
  chrome::AddTabAt(browser(), GURL("about:blank"), -1, true);

  const unsigned number_of_tabs = browser()->tab_strip_model()->count();
  EXPECT_EQ(2u, number_of_tabs);

  // Verify that the info bar is shown in every tab.
  for (unsigned i = 0; i < number_of_tabs; ++i) {
    ContentInfoBarManager* infobar_manager = GetInfoBarManagerFromTabIndex(i);
    ASSERT_EQ(1u, infobar_manager->infobars().size());

    auto* test_infobar = infobar_manager->infobars()[0]->delegate();
    ASSERT_EQ(ConfirmInfoBarDelegate::InfoBarIdentifier::
                  CHROME_FOR_TESTING_INFOBAR_DELEGATE,
              test_infobar->GetIdentifier());
  }
}

// Subclass for tests that require infobars to be disabled.
class ChromeForTestingInfoBarDisabledTest : public ChromeForTestingInfoBarTest {
 public:
  ChromeForTestingInfoBarDisabledTest() = default;

  ChromeForTestingInfoBarDisabledTest(
      const ChromeForTestingInfoBarDisabledTest&) = delete;
  ChromeForTestingInfoBarDisabledTest& operator=(
      const ChromeForTestingInfoBarDisabledTest&) = delete;

  ~ChromeForTestingInfoBarDisabledTest() override = default;

 protected:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    command_line->AppendSwitch(switches::kDisableInfoBars);
  }
};

IN_PROC_BROWSER_TEST_F(ChromeForTestingInfoBarDisabledTest,
                       NoInfoBarAppearsInitially) {
  ASSERT_EQ(0u, GetInfoBarManagerFromTabIndex(0)->infobars().size());
}

IN_PROC_BROWSER_TEST_F(ChromeForTestingInfoBarDisabledTest,
                       NoInfoBarAppearsInNewTabs) {
  ASSERT_EQ(0u, GetInfoBarManagerFromTabIndex(0)->infobars().size());

  // Open a second tab in the same window.
  chrome::AddTabAt(browser(), GURL("about:blank"), -1, true);

  ASSERT_EQ(0u, GetInfoBarManagerFromTabIndex(1)->infobars().size());
}

class TestInfoBarDelegate : public ConfirmInfoBarDelegate {
 public:
  static void Create(ContentInfoBarManager* infobar_manager,
                     bool has_buttons,
                     bool replace_existing = false) {
    infobar_manager->AddInfoBar(
        CreateConfirmInfoBar(std::unique_ptr<ConfirmInfoBarDelegate>(
            new TestInfoBarDelegate(has_buttons))),
        replace_existing);
  }

  TestInfoBarDelegate(const TestInfoBarDelegate&) = delete;
  TestInfoBarDelegate& operator=(const TestInfoBarDelegate&) = delete;

 private:
  explicit TestInfoBarDelegate(bool has_buttons) : has_buttons_(has_buttons) {}
  ~TestInfoBarDelegate() override = default;

  InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override {
    return InfoBarIdentifier::TEST_INFOBAR;
  }

  std::u16string GetMessageText() const override { return u"mock infobar"; }

  int GetButtons() const override {
    return has_buttons_ ? BUTTON_OK | BUTTON_CANCEL : BUTTON_NONE;
  }

  std::u16string GetButtonLabel(InfoBarButton button) const override {
    return button == BUTTON_OK ? u"allow" : u"deny";
  }

  const bool has_buttons_;
};

IN_PROC_BROWSER_TEST_F(ChromeForTestingInfoBarDisabledTest,
                       ChromeForTestingInfoBarWithButtonsVisibility) {
  ContentInfoBarManager* infobar_manager = GetActiveWebContentsInfoBarManager();
  ASSERT_TRUE(infobar_manager);

  // No inforbars should be shown upon start due to --disable-infobars.
  EXPECT_THAT(infobar_manager->infobars(), testing::IsEmpty());

  // Try to add infobar with no buttons and verify it was not added.
  TestInfoBarDelegate::Create(infobar_manager, /*has_buttons=*/false);

  EXPECT_THAT(infobar_manager->infobars(), testing::IsEmpty());

  // Try to add infobar with buttons and verify it was added.
  TestInfoBarDelegate::Create(infobar_manager, /*has_buttons=*/true);

  EXPECT_EQ(infobar_manager->infobars().size(), 1u);
  EXPECT_EQ(infobar_manager->infobars()[0]->GetIdentifier(),
            InfoBarDelegate::InfoBarIdentifier::TEST_INFOBAR);

  // Replace existing infobar with a new one that has no buttons and verify that
  // the existing infobar was removed and the new one was not added.
  TestInfoBarDelegate::Create(infobar_manager, /*has_buttons=*/false,
                              /*replace_existing=*/true);

  EXPECT_THAT(infobar_manager->infobars(), testing::IsEmpty());
}

}  // namespace

}  // namespace infobars