blob: c28a85a3787c61ca2ce1f43df40f30c396a8a64b [file] [log] [blame]
// Copyright 2020 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/views/bubble/webui_bubble_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/views/bubble/webui_bubble_dialog_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/test/browser_test.h"
#include "ui/webui/mojo_bubble_web_ui_controller.h"
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 webui_resizes_host = true,
bool esc_closes_ui = true)
: BubbleContentsWrapper(webui_url,
browser_context,
task_manager_string_id,
webui_resizes_host,
esc_closes_ui) {}
void ReloadWebContents() override {}
};
class WebUIBubbleManagerBrowserTest : public InProcessBrowserTest {
public:
WebUIBubbleManagerBrowserTest() = default;
WebUIBubbleManagerBrowserTest(const WebUIBubbleManagerBrowserTest&) = delete;
const WebUIBubbleManagerBrowserTest& operator=(
const WebUIBubbleManagerBrowserTest&) = delete;
~WebUIBubbleManagerBrowserTest() override = default;
// content::BrowserTestBase:
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
bubble_manager_ =
std::make_unique<WebUIBubbleManagerT<TestWebUIController>>(
BrowserView::GetBrowserViewForBrowser(browser()),
browser()->profile(), GURL("chrome://test"), 1);
}
void TearDownOnMainThread() override {
bubble_manager_.reset();
InProcessBrowserTest::TearDownOnMainThread();
}
WebUIBubbleManager* bubble_manager() { return bubble_manager_.get(); }
void DestroyBubbleManager() { bubble_manager_.reset(); }
private:
std::unique_ptr<WebUIBubbleManager> bubble_manager_;
};
IN_PROC_BROWSER_TEST_F(WebUIBubbleManagerBrowserTest, CreateAndCloseBubble) {
EXPECT_EQ(nullptr, bubble_manager()->GetBubbleWidget());
bubble_manager()->ShowBubble();
EXPECT_NE(nullptr, bubble_manager()->GetBubbleWidget());
EXPECT_FALSE(bubble_manager()->GetBubbleWidget()->IsClosed());
bubble_manager()->CloseBubble();
EXPECT_TRUE(bubble_manager()->GetBubbleWidget()->IsClosed());
}
IN_PROC_BROWSER_TEST_F(WebUIBubbleManagerBrowserTest,
ShowUISetsBubbleWidgetVisible) {
EXPECT_EQ(nullptr, bubble_manager()->GetBubbleWidget());
bubble_manager()->ShowBubble();
EXPECT_NE(nullptr, bubble_manager()->GetBubbleWidget());
EXPECT_FALSE(bubble_manager()->GetBubbleWidget()->IsClosed());
EXPECT_FALSE(bubble_manager()->GetBubbleWidget()->IsVisible());
bubble_manager()->bubble_view_for_testing()->ShowUI();
EXPECT_TRUE(bubble_manager()->GetBubbleWidget()->IsVisible());
bubble_manager()->CloseBubble();
EXPECT_TRUE(bubble_manager()->GetBubbleWidget()->IsClosed());
}
// Ensures that the WebUI bubble is destroyed synchronously with the manager.
// This guards against a potential UAF crash (see crbug.com/1345546).
IN_PROC_BROWSER_TEST_F(WebUIBubbleManagerBrowserTest,
ManagerDestructionClosesBubble) {
EXPECT_EQ(nullptr, bubble_manager()->GetBubbleWidget());
bubble_manager()->ShowBubble();
EXPECT_NE(nullptr, bubble_manager()->GetBubbleWidget());
base::WeakPtr<WebUIBubbleDialogView> bubble_view =
bubble_manager()->bubble_view_for_testing();
EXPECT_TRUE(bubble_view);
bubble_view->ShowUI();
EXPECT_TRUE(bubble_manager()->GetBubbleWidget()->IsVisible());
// Destroy the bubble manager without explicitly destroying the bubble. Ensure
// the bubble is closed synchronously.
DestroyBubbleManager();
EXPECT_FALSE(bubble_view);
}