blob: c34b04178af23839dd9dce7c717e48e6dc9efa7d [file] [log] [blame]
// Copyright 2021 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/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "chrome/browser/ui/extensions/extension_dialog_utils.h"
#include "chrome/browser/ui/extensions/extensions_dialogs.h"
#include "chrome/common/url_constants.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/constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/dialog_model.h"
#include "ui/color/color_id.h"
namespace {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class ExtensionInstallFrictionDialogAction {
kClose = 0,
kLearnMore = 1,
kContinueToInstall = 2,
kClosedWithoutUserAction = 3,
kMaxValue = kClosedWithoutUserAction,
};
void ReportExtensionInstallFrictionDialogAction(
ExtensionInstallFrictionDialogAction action) {
base::UmaHistogramEnumeration("Extensions.InstallFrictionDialogAction",
action);
}
class ExtensionInstallFrictionDialogDelegate : public ui::DialogModelDelegate {
public:
explicit ExtensionInstallFrictionDialogDelegate(
content::WebContents* web_contents,
base::OnceCallback<void(bool)> callback)
: original_web_contents_(web_contents->GetWeakPtr()),
callback_(std::move(callback)) {}
~ExtensionInstallFrictionDialogDelegate() override = default;
void OnDialogAccepted() {
ReportExtensionInstallFrictionDialogAction(
ExtensionInstallFrictionDialogAction::kContinueToInstall);
std::move(callback_).Run(true);
}
void OnDialogCanceled() {
ExtensionInstallFrictionDialogAction dialog_action =
learn_more_clicked_ ? ExtensionInstallFrictionDialogAction::kLearnMore
: ExtensionInstallFrictionDialogAction::kClose;
ReportExtensionInstallFrictionDialogAction(dialog_action);
std::move(callback_).Run(false);
}
void OnDialogDestroyed() {
if (callback_) {
// The dialog may close without firing any of the [accept | cancel |
// close] callbacks if e.g. the parent window closes. In this case, we
// have to manually run the callback.
ReportExtensionInstallFrictionDialogAction(
ExtensionInstallFrictionDialogAction::kClosedWithoutUserAction);
std::move(callback_).Run(false);
}
}
void OnLearnMoreLinkClicked() {
learn_more_clicked_ = true;
if (original_web_contents_) {
GURL url(chrome::kCwsEnhancedSafeBrowsingLearnMoreURL);
content::OpenURLParams params(
url, content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui::PAGE_TRANSITION_LINK, /*is_renderer_initiated=*/false);
original_web_contents_->OpenURL(params, {});
}
dialog_model()->host()->Close();
}
private:
base::WeakPtr<content::WebContents> original_web_contents_;
base::OnceCallback<void(bool)> callback_;
bool learn_more_clicked_ = false;
};
} // namespace
namespace extensions {
DEFINE_ELEMENT_IDENTIFIER_VALUE(kExtensionInstallFrictionLearnMoreLink);
void ShowExtensionInstallFrictionDialog(
content::WebContents* web_contents,
base::OnceCallback<void(bool)> callback) {
auto dialog_delegate_unique =
std::make_unique<ExtensionInstallFrictionDialogDelegate>(
web_contents, std::move(callback));
ExtensionInstallFrictionDialogDelegate* dialog_delegate =
dialog_delegate_unique.get();
std::unique_ptr<ui::DialogModel> dialog =
ui::DialogModel::Builder(std::move(dialog_delegate_unique))
.SetTitle(l10n_util::GetStringUTF16(
IDS_EXTENSION_PROMPT_INSTALL_FRICTION_TITLE))
.SetIcon(ui::ImageModel::FromVectorIcon(
vector_icons::kGppMaybeIcon, ui::kColorAlertMediumSeverityIcon,
extension_misc::EXTENSION_ICON_SMALLISH))
.AddOkButton(
base::BindOnce(
&ExtensionInstallFrictionDialogDelegate::OnDialogAccepted,
base::Unretained(dialog_delegate)),
ui::DialogModel::Button::Params().SetLabel(
l10n_util::GetStringUTF16(
IDS_EXTENSION_PROMPT_INSTALL_FRICTION_CONTINUE_BUTTON)))
.AddCancelButton(
base::BindOnce(
&ExtensionInstallFrictionDialogDelegate::OnDialogCanceled,
base::Unretained(dialog_delegate)),
ui::DialogModel::Button::Params().SetLabel(
l10n_util::GetStringUTF16(IDS_CLOSE)))
.SetCloseActionCallback(base::BindOnce(
&ExtensionInstallFrictionDialogDelegate::OnDialogCanceled,
base::Unretained(dialog_delegate)))
.SetDialogDestroyingCallback(base::BindOnce(
&ExtensionInstallFrictionDialogDelegate::OnDialogDestroyed,
base::Unretained(dialog_delegate)))
.OverrideDefaultButton(ui::mojom::DialogButton::kCancel)
.AddParagraph(ui::DialogModelLabel::CreateWithReplacement(
IDS_EXTENSION_PROMPT_INSTALL_FRICTION_WARNING_TEXT,
ui::DialogModelLabel::CreateLink(
IDS_LEARN_MORE,
base::BindRepeating(
&ExtensionInstallFrictionDialogDelegate::
OnLearnMoreLinkClicked,
base::Unretained(dialog_delegate)))),
/*header=*/std::u16string(),
/*id=*/kExtensionInstallFrictionLearnMoreLink)
.Build();
ShowWebModalDialog(web_contents, std::move(dialog));
}
} // namespace extensions