blob: 2af61f07972ad3042c77abe94b1e4d301aebe754 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/bubble/webui_bubble_manager.h"
#include "base/feature_list.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/bubble/bubble_contents_wrapper.h"
#include "chrome/browser/ui/views/bubble/webui_bubble_dialog_view.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chrome/test/views/chrome_views_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/webui/mojo_bubble_web_ui_controller.h"
namespace {
const char* kTestURL = "chrome://test";
} // namespace
class TestWebUIController : public ui::MojoBubbleWebUIController {
WEB_UI_CONTROLLER_TYPE_DECL();
};
WEB_UI_CONTROLLER_TYPE_IMPL(TestWebUIController)
template <>
class BubbleContentsWrapperT<TestWebUIController>
: public BubbleContentsWrapper {
public:
BubbleContentsWrapperT(const GURL& webui_url,
content::BrowserContext* browser_context,
int task_manager_string_id,
bool enable_extension_apis = false,
bool webui_resizes_host = true)
: BubbleContentsWrapper(browser_context,
task_manager_string_id,
enable_extension_apis,
webui_resizes_host) {}
void ReloadWebContents() override {}
};
class WebUIBubbleManagerTest : public ChromeViewsTestBase {
public:
WebUIBubbleManagerTest()
: profile_manager_(TestingBrowserProcess::GetGlobal()) {}
WebUIBubbleManagerTest(const WebUIBubbleManagerTest&) = delete;
WebUIBubbleManagerTest& operator=(const WebUIBubbleManagerTest&) = delete;
~WebUIBubbleManagerTest() override = default;
// ChromeViewsTestBase:
void SetUp() override {
scoped_feature_list_.InitWithFeatures(
{features::kWebUIBubblePerProfilePersistence}, {});
ASSERT_TRUE(profile_manager_.SetUp());
ChromeViewsTestBase::SetUp();
}
TestingProfileManager* profile_manager() { return &profile_manager_; }
private:
base::test::ScopedFeatureList scoped_feature_list_;
TestingProfileManager profile_manager_;
};
TEST_F(WebUIBubbleManagerTest, UsesPersistentContentsWrapperPerProfile) {
const char* kProfileName = "Person 1";
auto* test_profile = profile_manager()->CreateTestingProfile(kProfileName);
auto* service =
BubbleContentsWrapperServiceFactory::GetForProfile(test_profile, true);
ASSERT_NE(nullptr, service);
std::unique_ptr<views::Widget> anchor_widget =
CreateTestWidget(views::Widget::InitParams::TYPE_WINDOW);
auto bubble_manager =
std::make_unique<WebUIBubbleManagerT<TestWebUIController>>(
anchor_widget->GetContentsView(), test_profile, GURL(kTestURL), 1,
false);
bubble_manager->DisableCloseBubbleHelperForTesting();
// If using per-profile peristence the `contents_wrapper` should have been
// created before the bubble has been invoked.
BubbleContentsWrapper* contents_wrapper =
service->GetBubbleContentsWrapperFromURL(GURL(kTestURL));
EXPECT_NE(nullptr, contents_wrapper);
// Open the bubble, the `contents_wrapper` used should match the one returned
// from the BubbleContentsWrapperService.
EXPECT_EQ(nullptr, bubble_manager->GetBubbleWidget());
bubble_manager->ShowBubble();
EXPECT_NE(nullptr, bubble_manager->GetBubbleWidget());
EXPECT_FALSE(bubble_manager->GetBubbleWidget()->IsClosed());
EXPECT_EQ(contents_wrapper, bubble_manager->bubble_view_for_testing()
->get_contents_wrapper_for_testing());
// After closing the bubble the `contents_wrapper` should continue to persist.
bubble_manager->CloseBubble();
EXPECT_TRUE(bubble_manager->GetBubbleWidget()->IsClosed());
EXPECT_EQ(contents_wrapper,
service->GetBubbleContentsWrapperFromURL(GURL(kTestURL)));
profile_manager()->DeleteTestingProfile(kProfileName);
}
TEST_F(WebUIBubbleManagerTest,
PerProfileContentsWrapperNotUsedForOffTheRecordProfile) {
const char* kProfileName = "Person 1";
auto* test_profile = profile_manager()->CreateTestingProfile(kProfileName);
auto* otr_profile = test_profile->GetOffTheRecordProfile(
Profile::OTRProfileID::CreateUniqueForTesting(),
/*create_if_needed=*/true);
std::unique_ptr<views::Widget> anchor_widget =
CreateTestWidget(views::Widget::InitParams::TYPE_WINDOW);
auto bubble_manager =
std::make_unique<WebUIBubbleManagerT<TestWebUIController>>(
anchor_widget->GetContentsView(), otr_profile, GURL(kTestURL), 1,
false);
bubble_manager->DisableCloseBubbleHelperForTesting();
// The service should not exist for off the record profiles.
auto* service =
BubbleContentsWrapperServiceFactory::GetForProfile(otr_profile, true);
ASSERT_EQ(nullptr, service);
// Open the bubble for the given bubble manager
EXPECT_EQ(nullptr, bubble_manager->GetBubbleWidget());
bubble_manager->ShowBubble();
EXPECT_NE(nullptr, bubble_manager->GetBubbleWidget());
// The contents wrapper should exist despite `service` not existing for the
// off the record profile.
EXPECT_NE(nullptr, bubble_manager->bubble_view_for_testing()
->get_contents_wrapper_for_testing());
bubble_manager->CloseBubble();
EXPECT_TRUE(bubble_manager->GetBubbleWidget()->IsClosed());
bubble_manager->ResetContentsWrapperForTesting();
profile_manager()->DeleteTestingProfile(kProfileName);
}
#if !BUILDFLAG(IS_CHROMEOS_ASH) // No multi-profile on ChromeOS.
TEST_F(WebUIBubbleManagerTest,
UsesPersistentContentsWrapperPerProfileMultiProfile) {
const char* kProfileName1 = "Person 1";
const char* kProfileName2 = "Person 2";
auto* profile1 = profile_manager()->CreateTestingProfile(kProfileName1);
auto* profile2 = profile_manager()->CreateTestingProfile(kProfileName2);
auto* service1 =
BubbleContentsWrapperServiceFactory::GetForProfile(profile1, true);
auto* service2 =
BubbleContentsWrapperServiceFactory::GetForProfile(profile2, true);
std::unique_ptr<views::Widget> anchor_widget =
CreateTestWidget(views::Widget::InitParams::TYPE_WINDOW);
auto create_manager = [&](Profile* profile) {
auto manager = std::make_unique<WebUIBubbleManagerT<TestWebUIController>>(
anchor_widget->GetContentsView(), profile, GURL(kTestURL), 1, false);
manager->DisableCloseBubbleHelperForTesting();
return manager;
};
auto manager1 = create_manager(profile1);
auto manager2 = create_manager(profile1);
auto manager3 = create_manager(profile2);
BubbleContentsWrapper* contents_wrapper_profile1 =
service1->GetBubbleContentsWrapperFromURL(GURL(kTestURL));
BubbleContentsWrapper* contents_wrapper_profile2 =
service2->GetBubbleContentsWrapperFromURL(GURL(kTestURL));
// content wrappers for the same WebUI URL should be different per profile.
ASSERT_NE(nullptr, contents_wrapper_profile1);
ASSERT_NE(nullptr, contents_wrapper_profile2);
ASSERT_NE(contents_wrapper_profile1, contents_wrapper_profile2);
auto test_manager = [](WebUIBubbleManager* manager,
BubbleContentsWrapperService* service,
BubbleContentsWrapper* expected_wrapper) {
// Open the bubble for the given bubble manager
EXPECT_EQ(nullptr, manager->GetBubbleWidget());
manager->ShowBubble();
EXPECT_NE(nullptr, manager->GetBubbleWidget());
// The `expected_wrapper` matches the one used by the bubble.
EXPECT_EQ(
expected_wrapper,
manager->bubble_view_for_testing()->get_contents_wrapper_for_testing());
// Close the bubble, ensure the service's contents wrapper still exists and
// matches the `expected_wrapper`.
EXPECT_FALSE(manager->GetBubbleWidget()->IsClosed());
manager->CloseBubble();
EXPECT_TRUE(manager->GetBubbleWidget()->IsClosed());
EXPECT_EQ(expected_wrapper,
service->GetBubbleContentsWrapperFromURL(GURL(kTestURL)));
};
test_manager(manager1.get(), service1, contents_wrapper_profile1);
test_manager(manager2.get(), service1, contents_wrapper_profile1);
test_manager(manager3.get(), service2, contents_wrapper_profile2);
profile_manager()->DeleteTestingProfile(kProfileName1);
profile_manager()->DeleteTestingProfile(kProfileName2);
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)