blob: c9386b1c9aa48fa662111c03c5b93ca9b4865245 [file] [log] [blame]
// Copyright 2023 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_view_controller.h"
#include "base/i18n/case_conversion.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/extensions/extension_action_view_controller.h"
#include "chrome/browser/ui/extensions/extensions_container.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_page_view.h"
#include "chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/view_utils.h"
#include "ui/views/widget/widget.h"
namespace {
// Returns sorted extension ids based on their extensions name.
std::vector<std::string> SortExtensionsByName(
ToolbarActionsModel* toolbar_model) {
auto sort_by_name = [toolbar_model](const ToolbarActionsModel::ActionId a,
const ToolbarActionsModel::ActionId b) {
return base::i18n::ToLower(toolbar_model->GetExtensionName(a)) <
base::i18n::ToLower(toolbar_model->GetExtensionName(b));
};
std::vector<std::string> sorted_ids(toolbar_model->action_ids().begin(),
toolbar_model->action_ids().end());
std::sort(sorted_ids.begin(), sorted_ids.end(), sort_by_name);
return sorted_ids;
}
} // namespace
ExtensionsMenuViewController::ExtensionsMenuViewController(
Browser* browser,
ExtensionsContainer* extensions_container,
views::View* bubble_contents,
views::BubbleDialogDelegate* bubble_delegate)
: browser_(browser),
extensions_container_(extensions_container),
bubble_contents_(bubble_contents),
bubble_delegate_(bubble_delegate),
toolbar_model_(ToolbarActionsModel::Get(browser_->profile())) {
browser_->tab_strip_model()->AddObserver(this);
}
void ExtensionsMenuViewController::OpenMainPage() {
auto main_page = std::make_unique<ExtensionsMenuMainPageView>(browser_, this);
// Populate.
bool allow_pinning = extensions_container_->CanShowActionsInToolbar();
std::vector<std::string> sorted_ids = SortExtensionsByName(toolbar_model_);
for (size_t i = 0; i < sorted_ids.size(); ++i) {
// TODO(emiliapaz): Under MVC architecte, view should not own the view
// controller. However, the current extensions structure depends on this
// thus a major restructure is needed.
std::unique_ptr<ExtensionActionViewController> action_controller =
ExtensionActionViewController::Create(sorted_ids[i], browser_,
extensions_container_);
main_page->CreateAndInsertMenuItem(std::move(action_controller),
allow_pinning, i);
}
SwitchToPage(std::move(main_page));
}
void ExtensionsMenuViewController::OpenSitePermissionsPage() {
auto site_permissions_page =
std::make_unique<ExtensionsMenuSitePermissionsPage>(this);
SwitchToPage(std::move(site_permissions_page));
}
void ExtensionsMenuViewController::CloseBubble() {
bubble_contents_->GetWidget()->CloseWithReason(
views::Widget::ClosedReason::kCloseButtonClicked);
}
void ExtensionsMenuViewController::TabChangedAt(content::WebContents* contents,
int index,
TabChangeType change_type) {
DCHECK(current_page_);
current_page_->Update();
}
void ExtensionsMenuViewController::OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) {
DCHECK(current_page_);
current_page_->Update();
}
// TODO(crbug.com/1390952): Listen for "toolbar pinned actions changed" to
// update the pin button. Currently pin button icon is not updated after
// clicking on it.
ExtensionsMenuMainPageView*
ExtensionsMenuViewController::GetMainPageViewForTesting() {
DCHECK(current_page_);
return views::AsViewClass<ExtensionsMenuMainPageView>(current_page_);
}
void ExtensionsMenuViewController::SwitchToPage(
std::unique_ptr<ExtensionsMenuPageView> page) {
if (current_page_) {
bubble_contents_->RemoveChildViewT(current_page_.get());
}
current_page_ = bubble_contents_->AddChildView(std::move(page));
// Only resize the menu if the bubble is created, since page could be added to
// the menu beforehand and delegate wouldn't know the bubble bounds.
if (bubble_delegate_->GetBubbleFrameView()) {
bubble_delegate_->SizeToContents();
}
}