blob: be1e1e82a6709e130c7618292c8e7fb914c9924d [file] [log] [blame]
// Copyright 2025 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/ui/pdf/infobar/pdf_infobar_controller.h"
#include <memory>
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/browser_window/test/mock_browser_window_interface.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h"
#include "chrome/browser/ui/tabs/test_util.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gtest/include/gtest/gtest.h"
class PdfInfoBarControllerTest : public testing::Test {
protected:
PdfInfoBarControllerTest()
: profile_(std::make_unique<TestingProfile>()),
delegate_(std::make_unique<TestTabStripModelDelegate>()),
tab_strip_model_(
std::make_unique<TabStripModel>(delegate(), profile())),
browser_window_interface_(
std::make_unique<MockBrowserWindowInterface>()) {
ON_CALL(*browser_window_interface_, GetTabStripModel)
.WillByDefault(::testing::Return(tab_strip_model()));
ON_CALL(*browser_window_interface_, GetProfile)
.WillByDefault(::testing::Return(profile()));
delegate_->SetBrowserWindowInterface(browser_window_interface());
}
~PdfInfoBarControllerTest() override {
// Break loop so we can deconstruct without dangling pointers.
delegate_->SetBrowserWindowInterface(nullptr);
}
void AddTab() {
std::unique_ptr<content::WebContents> web_contents =
content::WebContentsTester::CreateTestWebContents(profile(), nullptr);
tab_strip_model_->AppendWebContents(std::move(web_contents), true);
}
void SetUp() override {
AddTab();
infobars::ContentInfoBarManager::CreateForWebContents(
tab_strip_model_->GetActiveWebContents());
}
void SetBrowserType(BrowserWindowInterface::Type type) {
ON_CALL(*browser_window_interface_, GetType)
.WillByDefault(::testing::Return(type));
}
// Calls `MaybeShowInfoBarCallback()` with the given `default_state` and
// `browser_type`. Returns true if the infobar was shown, false if not.
bool DidShowInfoBar(BrowserWindowInterface::Type browser_type,
shell_integration::DefaultWebClientState default_state) {
auto* infobar_manager = infobars::ContentInfoBarManager::FromWebContents(
tab_strip_model()->GetActiveWebContents());
CHECK(infobar_manager);
CHECK(infobar_manager->infobars().empty());
SetBrowserType(browser_type);
PdfInfoBarController controller{browser_window_interface()};
controller.MaybeShowInfoBarCallback(default_state);
// Return true if an infobar was created.
bool did_show_infobar = !infobar_manager->infobars().empty();
if (did_show_infobar) {
// Clear the infobar to ensure `controller` stops observing
// `infobar_manager` before being destroyed.
infobar_manager->RemoveAllInfoBars(false);
}
return did_show_infobar;
}
TestingPrefServiceSimple* local_state() { return local_state_.Get(); }
TestingProfile* profile() { return profile_.get(); }
TestTabStripModelDelegate* delegate() { return delegate_.get(); }
TabStripModel* tab_strip_model() { return tab_strip_model_.get(); }
MockBrowserWindowInterface* browser_window_interface() {
return browser_window_interface_.get();
}
base::test::ScopedFeatureList& feature_list() { return feature_list_; }
private:
// Must be the first member.
content::BrowserTaskEnvironment task_environment_;
base::test::ScopedFeatureList feature_list_;
// Must be before `profile_`.
ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()};
// `ChromeLayoutProvider::Get()` is called when an infobar is created.
ChromeLayoutProvider layout_provider_;
content::RenderViewHostTestEnabler rvh_test_enabler_;
const std::unique_ptr<TestingProfile> profile_;
const std::unique_ptr<TestTabStripModelDelegate> delegate_;
const std::unique_ptr<TabStripModel> tab_strip_model_;
const std::unique_ptr<MockBrowserWindowInterface> browser_window_interface_;
tabs::PreventTabFeatureInitialization prevent_;
};
class PdfInfoBarControllerPdfLoadTest : public PdfInfoBarControllerTest {
void SetUp() override {
feature_list().InitAndEnableFeatureWithParameters(
features::kPdfInfoBar, {{"trigger", "pdf-load"}});
PdfInfoBarControllerTest::SetUp();
}
};
// Register to be called when the active tab changes if the browser is normal.
TEST_F(PdfInfoBarControllerPdfLoadTest, RegisterActiveTabDidChangeNormal) {
SetBrowserType(BrowserWindowInterface::Type::TYPE_NORMAL);
EXPECT_CALL(*(browser_window_interface()), RegisterActiveTabDidChange);
PdfInfoBarController controller{browser_window_interface()};
}
// Don't register for active tab changes if the browser is not a normal type.
TEST_F(PdfInfoBarControllerPdfLoadTest, RegisterActiveTabDidChangeApp) {
SetBrowserType(BrowserWindowInterface::Type::TYPE_APP);
EXPECT_CALL(*(browser_window_interface()), RegisterActiveTabDidChange)
.Times(0);
PdfInfoBarController controller{browser_window_interface()};
}
class PdfInfoBarControllerStartupTest : public PdfInfoBarControllerTest {
void SetUp() override {
feature_list().InitAndEnableFeatureWithParameters(features::kPdfInfoBar,
{{"trigger", "startup"}});
PdfInfoBarControllerTest::SetUp();
}
};
// Show the infobar if the feature is enabled, the browser type is normal, and
// Chrome is not the default PDF viewer.
TEST_F(PdfInfoBarControllerStartupTest, MaybeShowInfoBarCallback) {
EXPECT_TRUE(
DidShowInfoBar(BrowserWindowInterface::Type::TYPE_NORMAL,
shell_integration::DefaultWebClientState::NOT_DEFAULT));
}
// Don't show the infobar if Chrome is already the default PDF viewer.
TEST_F(PdfInfoBarControllerStartupTest, DontShowInfoBarIfChromeIsDefault) {
EXPECT_FALSE(
DidShowInfoBar(BrowserWindowInterface::Type::TYPE_NORMAL,
shell_integration::DefaultWebClientState::IS_DEFAULT));
}
// Don't show the infobar if another Chrome channel is the default PDF viewer.
TEST_F(PdfInfoBarControllerStartupTest,
DontShowInfoBarIfAnotherChromeIsDefault) {
EXPECT_FALSE(DidShowInfoBar(
BrowserWindowInterface::Type::TYPE_NORMAL,
shell_integration::DefaultWebClientState::OTHER_MODE_IS_DEFAULT));
}
// Don't show the infobar if Chrome's PDF viewer is disabled.
TEST_F(PdfInfoBarControllerStartupTest, DontShowInfoBarIfPdfViewerDisabled) {
profile()->GetPrefs()->SetBoolean(prefs::kPluginsAlwaysOpenPdfExternally,
true);
EXPECT_FALSE(
DidShowInfoBar(BrowserWindowInterface::Type::TYPE_NORMAL,
shell_integration::DefaultWebClientState::NOT_DEFAULT));
}
// Don't show the infobar if default apps are managed by a policy.
TEST_F(PdfInfoBarControllerStartupTest,
DontShowInfoBarIfDefaultIsPolicyControlled) {
local_state()->SetManagedPref(prefs::kDefaultBrowserSettingEnabled,
base::Value(true));
EXPECT_FALSE(
DidShowInfoBar(BrowserWindowInterface::Type::TYPE_NORMAL,
shell_integration::DefaultWebClientState::NOT_DEFAULT));
}