blob: ef2d5d13fdce03750d8a809e69bd63b3556397c8 [file] [log] [blame]
// Copyright 2019 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/extensions/extensions_menu_test_util.h"
#include <algorithm>
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/extensions/extension_action_view_model.h"
#include "chrome/browser/ui/toolbar/toolbar_action_view_model.h"
#include "chrome/browser/ui/views/extensions/extension_popup.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_button.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_coordinator.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_item_view.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_view.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_view_platform_delegate_views.h"
#include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h"
#include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h"
#include "chrome/browser/ui/views/extensions/extensions_toolbar_coordinator.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "extensions/common/extension_features.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/image/image.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/layout/animating_layout_manager_test_util.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/test/button_test_api.h"
#include "ui/views/view.h"
#include "ui/views/view_utils.h"
#if BUILDFLAG(IS_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#endif
ExtensionsMenuTestUtil::ExtensionsMenuTestUtil(Browser* browser)
: scoped_allow_extensions_menu_instances_(
ExtensionsMenuView::AllowInstancesForTesting()),
browser_(browser) {
extensions_container_ = BrowserView::GetBrowserViewForBrowser(browser_)
->toolbar()
->extensions_container();
}
ExtensionsMenuTestUtil::~ExtensionsMenuTestUtil() {
if (!IsExtensionsMenuShowing()) {
return;
}
if (base::FeatureList::IsEnabled(
extensions_features::kExtensionsMenuAccessControl)) {
extensions_container_->GetExtensionsMenuCoordinatorForTesting()->Hide();
} else {
menu_view_->GetWidget()->CloseNow();
}
}
void ExtensionsMenuTestUtil::OnViewIsDeleting(views::View* observed_view) {
CHECK_EQ(observed_view, menu_view_);
menu_view_ = nullptr;
}
int ExtensionsMenuTestUtil::NumberOfBrowserActions() {
return extensions_container_->GetNumberOfActionsForTesting();
}
bool ExtensionsMenuTestUtil::HasAction(const extensions::ExtensionId& id) {
return extensions_container_->GetActionForId(id) != nullptr;
}
void ExtensionsMenuTestUtil::InspectPopup(const extensions::ExtensionId& id) {
auto* view_model = static_cast<ExtensionActionViewModel*>(
extensions_container_->GetActionForId(id));
DCHECK(view_model);
view_model->InspectPopup();
}
gfx::Image ExtensionsMenuTestUtil::GetIcon(const extensions::ExtensionId& id) {
ToolbarActionView* action_view = extensions_container_->GetViewForId(id);
DCHECK(action_view);
return gfx::Image(action_view->GetIconForTest());
}
void ExtensionsMenuTestUtil::Press(const extensions::ExtensionId& id) {
OpenExtensionsMenu();
ExtensionMenuItemView* view = GetMenuItemViewForId(id);
DCHECK(view);
ExtensionsMenuButton* primary_button =
view->primary_action_button_for_testing();
views::test::ButtonTestApi(primary_button).NotifyDefaultMouseClick();
}
gfx::NativeView ExtensionsMenuTestUtil::GetPopupNativeView() {
ToolbarActionViewModel* popup_owner =
extensions_container_->popup_owner_for_testing();
return popup_owner ? popup_owner->GetPopupNativeView() : gfx::NativeView();
}
bool ExtensionsMenuTestUtil::HasPopup() {
return !!GetPopupNativeView();
}
bool ExtensionsMenuTestUtil::HidePopup() {
// ExtensionsToolbarContainer::HideActivePopup() is private. Get around it by
// casting to an ExtensionsContainer.
static_cast<ExtensionsContainer*>(extensions_container_)->HideActivePopup();
return !HasPopup();
}
void ExtensionsMenuTestUtil::WaitForExtensionsContainerLayout() {
views::test::WaitForAnimatingLayoutManager(
static_cast<views::View*>(extensions_container_));
}
gfx::Size ExtensionsMenuTestUtil::GetMinPopupSize() {
return ExtensionPopup::kMinSize;
}
gfx::Size ExtensionsMenuTestUtil::GetMaxPopupSize() {
return ExtensionPopup::kMaxSize;
}
gfx::Size ExtensionsMenuTestUtil::GetMaxAvailableSizeToFitBubbleOnScreen(
const extensions::ExtensionId& id) {
#if BUILDFLAG(IS_OZONE)
if (!ui::OzonePlatform::GetInstance()
->GetPlatformProperties()
.supports_global_screen_coordinates) {
return ExtensionPopup::kMaxSize;
}
#endif
return views::BubbleDialogDelegate::GetMaxAvailableScreenSpaceToPlaceBubble(
extensions_container_->GetReferenceButtonForPopup(id),
views::BubbleBorder::TOP_RIGHT,
views::PlatformStyle::kAdjustBubbleIfOffscreen,
views::BubbleFrameView::PreferredArrowAdjustment::kMirror);
}
void ExtensionsMenuTestUtil::OpenExtensionsMenu() {
if (IsExtensionsMenuShowing()) {
return;
}
std::unique_ptr<views::BubbleDialogDelegate> bubble_dialog;
if (base::FeatureList::IsEnabled(
extensions_features::kExtensionsMenuAccessControl)) {
bubble_dialog =
extensions_container_->GetExtensionsMenuCoordinatorForTesting()
->CreateExtensionsMenuBubbleDialogDelegateForTesting(
extensions_container_->GetExtensionsButton(),
extensions_container_);
} else {
bubble_dialog = std::make_unique<ExtensionsMenuView>(
extensions_container_->GetExtensionsButton(), browser_,
extensions_container_);
menu_view_ = views::AsViewClass<ExtensionsMenuView>(
bubble_dialog->GetContentsView());
menu_view_->View::AddObserver(this);
}
views::BubbleDialogDelegate::CreateBubble(std::move(bubble_dialog));
}
bool ExtensionsMenuTestUtil::IsExtensionsMenuShowing() {
return base::FeatureList::IsEnabled(
extensions_features::kExtensionsMenuAccessControl)
? extensions_container_->GetExtensionsMenuCoordinatorForTesting()
->IsShowing()
: menu_view_;
}
ExtensionMenuItemView* ExtensionsMenuTestUtil::GetMenuItemViewForId(
const extensions::ExtensionId& id) {
base::flat_set<raw_ptr<ExtensionMenuItemView, CtnExperimental>> menu_items;
if (base::FeatureList::IsEnabled(
extensions_features::kExtensionsMenuAccessControl)) {
ExtensionsMenuMainPageView* main_page =
extensions_container_->GetExtensionsMenuCoordinatorForTesting()
->GetDelegateForTesting()
->GetMainPageViewForTesting();
DCHECK(main_page);
auto items = main_page->GetMenuItems();
menu_items = {items.begin(), items.end()};
} else {
menu_items = menu_view_->extensions_menu_items_for_testing();
}
auto iter = std::ranges::find(
menu_items, id,
[](ExtensionMenuItemView* view) { return view->view_model()->GetId(); });
return (iter == menu_items.end()) ? nullptr : *iter;
}
// static
std::unique_ptr<ExtensionActionTestHelper> ExtensionActionTestHelper::Create(
Browser* browser) {
return std::make_unique<ExtensionsMenuTestUtil>(browser);
}