blob: 7691c64764ca997c735db1e7b9bff6cb84ed6ae2 [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 "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/extensions/controlled_home_dialog_controller.h"
#include "chrome/browser/ui/extensions/extension_dialog_utils.h"
#include "chrome/browser/ui/extensions/extensions_dialogs.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "components/vector_icons/vector_icons.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/extension_id.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/dialog_model.h"
#include "ui/base/models/dialog_model_field.h"
namespace {
// Model delegate that notifies the `controller_` when a click event occurs in
// the controlled home dialog.
class ControlledHomeDialogDelegate
: public ui::DialogModelDelegate,
public extensions::ExtensionRegistryObserver {
public:
explicit ControlledHomeDialogDelegate(
Profile* profile,
std::unique_ptr<ControlledHomeDialogControllerInterface> controller)
: controller_(std::move(controller)) {
extension_registry_observation_.Observe(
extensions::ExtensionRegistry::Get(profile));
}
void OnDialogAccepted() {
controller_->OnBubbleClosed(
ControlledHomeDialogControllerInterface::CloseAction::CLOSE_EXECUTE);
}
void OnDialogCancelled() {
controller_->OnBubbleClosed(ControlledHomeDialogControllerInterface::
CloseAction::CLOSE_DISMISS_USER_ACTION);
}
void OnLearnMoreClicked() {
controller_->OnBubbleClosed(
ControlledHomeDialogControllerInterface::CloseAction::CLOSE_LEARN_MORE);
}
void OnDialogClosed() {
controller_->OnBubbleClosed(ControlledHomeDialogControllerInterface::
CloseAction::CLOSE_DISMISS_DEACTIVATION);
}
ControlledHomeDialogControllerInterface* controller() {
return controller_.get();
}
private:
void CloseDialog() { dialog_model()->host()->Close(); }
// ExtensionRegistryObserver:
void OnExtensionUnloaded(
content::BrowserContext* browser_context,
const extensions::Extension* extension,
extensions::UnloadedExtensionReason reason) override {
if (extension->id() != controller_->GetAnchorActionId()) {
return;
}
CloseDialog();
}
void OnExtensionUninstalled(content::BrowserContext* browser_context,
const extensions::Extension* extension,
extensions::UninstallReason reason) override {
if (extension->id() != controller_->GetAnchorActionId()) {
return;
}
CloseDialog();
}
void OnShutdown(extensions::ExtensionRegistry* registry) override {
// It is possible that the extension registry is destroyed before the
// dialog. In such case, the controller should no longer observe the
// registry.
DCHECK(extension_registry_observation_.IsObservingSource(registry));
extension_registry_observation_.Reset();
}
std::unique_ptr<ControlledHomeDialogControllerInterface> controller_;
base::ScopedObservation<extensions::ExtensionRegistry,
extensions::ExtensionRegistryObserver>
extension_registry_observation_{this};
};
} // namespace
namespace extensions {
DEFINE_ELEMENT_IDENTIFIER_VALUE(kControlledHomeDialogCancelButtonElementId);
void ShowControlledHomeDialog(
Profile* profile,
gfx::NativeWindow parent,
std::unique_ptr<ControlledHomeDialogControllerInterface>
dialog_controller_unique) {
auto dialog_delegate_unique = std::make_unique<ControlledHomeDialogDelegate>(
profile, std::move(dialog_controller_unique));
ControlledHomeDialogDelegate* dialog_delegate = dialog_delegate_unique.get();
ControlledHomeDialogControllerInterface* dialog_controller =
dialog_delegate->controller();
ui::DialogModel::Builder dialog_builder =
ui::DialogModel::Builder(std::move(dialog_delegate_unique));
dialog_builder.SetTitle(dialog_controller->GetHeadingText())
.AddParagraph(ui::DialogModelLabel(dialog_controller->GetBodyText()))
.AddCancelButton(
base::BindOnce(&ControlledHomeDialogDelegate::OnDialogCancelled,
base::Unretained(dialog_delegate)),
ui::DialogModel::Button::Params()
.SetLabel(dialog_controller->GetDismissButtonText())
.SetId(kControlledHomeDialogCancelButtonElementId))
.SetCloseActionCallback(
base::BindOnce(&ControlledHomeDialogDelegate::OnDialogClosed,
base::Unretained(dialog_delegate)));
if (dialog_controller->IsPolicyIndicationNeeded()) {
dialog_builder.AddMenuItem(
ui::ImageModel::FromVectorIcon(vector_icons::kBusinessIcon,
ui::kColorIcon, 16),
l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSTALLED_BY_ADMIN),
base::DoNothing(),
ui::DialogModelMenuItem::Params().SetIsEnabled(false));
} else {
dialog_builder.AddParagraph(ui::DialogModelLabel::CreateWithReplacement(
IDS_EXTENSIONS_CONTROLLED_HOME_DIALOG_LEARN_MORE_LINK,
ui::DialogModelLabel::CreateLink(
IDS_LEARN_MORE,
base::BindRepeating(
&ControlledHomeDialogDelegate::OnLearnMoreClicked,
base::Unretained(dialog_delegate)))));
}
std::u16string ok_button_text = dialog_controller->GetActionButtonText();
if (!ok_button_text.empty()) {
dialog_builder.AddOkButton(
base::BindOnce(&ControlledHomeDialogDelegate::OnDialogAccepted,
base::Unretained(dialog_delegate)),
ui::DialogModel::Button::Params().SetLabel(ok_button_text));
}
ShowDialog(parent, dialog_controller->GetAnchorActionId(),
dialog_builder.Build());
dialog_controller->OnBubbleShown();
}
} // namespace extensions