Commit 1c92b3fd authored by Anthony Vallee-Dubois's avatar Anthony Vallee-Dubois Committed by Chromium LUCI CQ

Add custom message related fields to content analysis dialog

Bug: 1166369
Change-Id: I32459ec22d8a4a6bd57d8ae0a17a3850a365fc57
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2625914
Commit-Queue: anthonyvd <anthonyvd@chromium.org>
Reviewed-by: default avatarDominique Fauteux-Chapleau <domfc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843330}
parent 191677c8
......@@ -10954,6 +10954,12 @@ Please help our engineers fix this problem. Tell us what happened right before y
=1 {This file is encrypted. Ask its owner to decrypt.}
other {Some of these files are encrypted. Ask their owner to decrypt.}}
</message>
<message name="IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE" desc="Message shown around the custom message provided by the administrator when deep scanning returns a failure.">
Your administrator says "<ph name="CUSTOM_MESSAGE">$1<ex>Please don't upload this type of data.</ex></ph>".
</message>
<message name="IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE_LEARN_MORE_LINK" desc="Text value of the link passed for the custom message set by the administrator when deep scanning returns a failure.">
Learn more
</message>
<!-- Deep scanning open now dialog strings -->
......
1d4a27fcac3fdb3ebd93f07c16e91791422d0da2
\ No newline at end of file
1d4a27fcac3fdb3ebd93f07c16e91791422d0da2
\ No newline at end of file
......@@ -61,6 +61,23 @@ AnalysisServiceSettings::AnalysisServiceSettings(
settings_value.FindBoolKey(kKeyBlockUnsupportedFileTypes).value_or(false);
minimum_data_size_ =
settings_value.FindIntKey(kKeyMinimumDataSize).value_or(100);
const base::Value* custom_messages =
settings_value.FindListKey(kKeyCustomMessages);
if (custom_messages && custom_messages->is_list() &&
!custom_messages->GetList().empty()) {
// As of now, this list can only contain one value. At some point, it
// might be necessary to iterate further in order to find the most
// appropriate message, for instance by considering the message and
// browser's locales or other signals.
const base::Value& value = custom_messages->GetList()[0];
const std::string* message = value.FindStringKey(kKeyCustomMessagesMessage);
custom_message_text_ = message ? *message : "";
const std::string* url =
value.FindStringKey(kKeyCustomMessagesLearnMoreUrl);
custom_message_learn_more_url_ = url ? GURL(*url) : GURL();
}
}
// static
......@@ -108,6 +125,8 @@ base::Optional<AnalysisSettings> AnalysisServiceSettings::GetAnalysisSettings(
settings.analysis_url = GURL(service_provider_->analysis_url());
DCHECK(settings.analysis_url.is_valid());
settings.minimum_data_size = minimum_data_size_;
settings.custom_message_text = custom_message_text_;
settings.custom_message_learn_more_url = custom_message_learn_more_url_;
return settings;
}
......
......@@ -95,6 +95,8 @@ class AnalysisServiceSettings {
bool block_large_files_ = false;
bool block_unsupported_file_types_ = false;
size_t minimum_data_size_ = 100;
std::string custom_message_text_;
GURL custom_message_learn_more_url_;
};
} // namespace enterprise_connectors
......
......@@ -29,6 +29,9 @@ constexpr char kKeyBlockLargeFiles[] = "block_large_files";
constexpr char kKeyBlockUnsupportedFileTypes[] = "block_unsupported_file_types";
constexpr char kKeyMinimumDataSize[] = "minimum_data_size";
constexpr char kKeyEnabledEventNames[] = "enabled_event_names";
constexpr char kKeyCustomMessages[] = "custom_messages";
constexpr char kKeyCustomMessagesMessage[] = "message";
constexpr char kKeyCustomMessagesLearnMoreUrl[] = "learn_more_url";
enum class ReportingConnector {
SECURITY_EVENT,
......@@ -56,6 +59,8 @@ struct AnalysisSettings {
bool block_password_protected_files = false;
bool block_large_files = false;
bool block_unsupported_file_types = false;
std::string custom_message_text;
GURL custom_message_learn_more_url;
// Minimum text size for BulkDataEntry scans. 0 means no minimum.
size_t minimum_data_size = 100;
......
......@@ -294,6 +294,9 @@ void ContentAnalysisDelegate::CreateForWebContents(
Factory* testing_factory = GetFactoryStorage();
bool wait_for_verdict = data.settings.block_until_verdict ==
enterprise_connectors::BlockUntilVerdict::BLOCK;
std::string custom_message_text = data.settings.custom_message_text;
GURL custom_message_learn_more_url =
data.settings.custom_message_learn_more_url;
// Using new instead of std::make_unique<> to access non public constructor.
auto delegate =
......@@ -571,7 +574,8 @@ bool ContentAnalysisDelegate::UpdateDialog() {
if (!dialog_)
return false;
dialog_->ShowResult(final_result_);
dialog_->ShowResult(final_result_, data_.settings.custom_message_text,
data_.settings.custom_message_learn_more_url);
return true;
}
......
......@@ -33,6 +33,7 @@
#include "ui/views/border.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/link.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/throbber.h"
#include "ui/views/layout/box_layout.h"
......@@ -212,6 +213,14 @@ void ContentAnalysisDialog::CancelButtonCallback() {
delegate_->Cancel(is_warning());
}
void ContentAnalysisDialog::LearnMoreLinkClickedCallback(
const ui::Event& event) {
web_contents_->OpenURL(
content::OpenURLParams(final_learn_more_url_, content::Referrer(),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui::PAGE_TRANSITION_LINK, false));
}
void ContentAnalysisDialog::SuccessCallback() {
#if defined(USE_AURA)
if (web_contents_) {
......@@ -268,6 +277,15 @@ views::View* ContentAnalysisDialog::GetContentsView() {
// Add the side icon.
icon_and_message_row->AddChildView(CreateSideIcon());
auto message_and_link_column = std::make_unique<views::View>();
auto* column_layout = message_and_link_column->SetLayoutManager(
std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical));
column_layout->set_main_axis_alignment(
views::BoxLayout::MainAxisAlignment::kCenter);
column_layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kStart);
// Add the message.
auto label = std::make_unique<DeepScanningMessageView>(this);
label->SetText(GetDialogMessage());
......@@ -275,8 +293,21 @@ views::View* ContentAnalysisDialog::GetContentsView() {
label->SetMultiLine(true);
label->SetVerticalAlignment(gfx::ALIGN_MIDDLE);
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
message_ = icon_and_message_row->AddChildView(std::move(label));
message_ = message_and_link_column->AddChildView(std::move(label));
// Add the Learn More link but hide it so it can only be displayed when
// required.
auto learn_more_link =
std::make_unique<views::Link>(l10n_util::GetStringUTF16(
IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE_LEARN_MORE_LINK));
learn_more_link->SetCallback(base::BindRepeating(
&ContentAnalysisDialog::LearnMoreLinkClickedCallback,
base::Unretained(this)));
learn_more_link->SetVisible(false);
learn_more_link_ =
message_and_link_column->AddChildView(std::move(learn_more_link));
icon_and_message_row->AddChildView(std::move(message_and_link_column));
layout->AddView(std::move(icon_and_message_row));
// Add padding to distance the message from the button(s).
......@@ -306,9 +337,14 @@ void ContentAnalysisDialog::WebContentsDestroyed() {
}
void ContentAnalysisDialog::ShowResult(
ContentAnalysisDelegate::FinalResult result) {
ContentAnalysisDelegate::FinalResult result,
const std::string& custom_message,
const GURL& learn_more_url) {
DCHECK(is_pending());
final_result_ = result;
final_custom_message_ = custom_message;
final_learn_more_url_ = learn_more_url;
switch (final_result_) {
case ContentAnalysisDelegate::FinalResult::ENCRYPTED_FILES:
case ContentAnalysisDelegate::FinalResult::LARGE_FILES:
......@@ -373,6 +409,14 @@ void ContentAnalysisDialog::UpdateDialog() {
message_->SetText(new_message);
message_->GetViewAccessibility().AnnounceText(std::move(new_message));
// Update the visibility of the Learn More link, which should only be visible
// if the dialog is in the warning or failure state, and there's a link to
// display.
learn_more_link_->SetVisible(
(dialog_status_ == DeepScanningDialogStatus::FAILURE ||
dialog_status_ == DeepScanningDialogStatus::WARNING) &&
(final_learn_more_url_.is_valid() && !final_learn_more_url_.is_empty()));
// Resize the dialog's height. This is needed since the text might take more
// lines after changing.
int text_height = message_->GetRequiredLines() * message_->GetLineHeight();
......@@ -432,7 +476,7 @@ void ContentAnalysisDialog::Resize(int height_to_add) {
bounds_animator_->SetAnimationDuration(kResizeAnimationDuration);
DCHECK(widget->GetRootView());
DCHECK_EQ(widget->GetRootView()->children().size(), 1u);
DCHECK_EQ(widget->GetRootView()->children().size(), 2u);
views::View* view_to_resize = widget->GetRootView()->children()[0];
// Start the animation.
......@@ -603,6 +647,11 @@ base::string16 ContentAnalysisDialog::GetPendingMessage() const {
base::string16 ContentAnalysisDialog::GetFailureMessage() const {
DCHECK(is_failure());
// If the admin has specified a custom message for this failure, it takes
// precedence over the generic ones.
if (has_custom_message())
return GetCustomMessage();
if (final_result_ == ContentAnalysisDelegate::FinalResult::LARGE_FILES) {
return l10n_util::GetPluralStringFUTF16(
IDS_DEEP_SCANNING_DIALOG_LARGE_FILE_FAILURE_MESSAGE, files_count_);
......@@ -619,6 +668,12 @@ base::string16 ContentAnalysisDialog::GetFailureMessage() const {
base::string16 ContentAnalysisDialog::GetWarningMessage() const {
DCHECK(is_warning());
// If the admin has specified a custom message for this warning, it takes
// precedence over the generic one.
if (has_custom_message())
return GetCustomMessage();
return l10n_util::GetPluralStringFUTF16(
IDS_DEEP_SCANNING_DIALOG_UPLOAD_WARNING_MESSAGE, files_count_);
}
......@@ -629,6 +684,13 @@ base::string16 ContentAnalysisDialog::GetSuccessMessage() const {
IDS_DEEP_SCANNING_DIALOG_SUCCESS_MESSAGE, files_count_);
}
base::string16 ContentAnalysisDialog::GetCustomMessage() const {
DCHECK(is_warning() || is_failure());
DCHECK(has_custom_message());
return l10n_util::GetStringFUTF16(IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE,
base::ASCIIToUTF16(final_custom_message_));
}
const gfx::ImageSkia* ContentAnalysisDialog::GetTopImage() const {
const bool use_dark = color_utils::IsDark(GetBackgroundColor(GetWidget()));
const bool treat_as_text_paste =
......
......@@ -27,6 +27,7 @@ class ImageSkia;
namespace views {
class ImageView;
class Label;
class Link;
class Throbber;
class Widget;
} // namespace views
......@@ -123,7 +124,9 @@ class ContentAnalysisDialog : public views::DialogDelegate,
// Updates the dialog with the result, and simply delete it from memory if
// nothing should be shown.
void ShowResult(ContentAnalysisDelegate::FinalResult result);
void ShowResult(ContentAnalysisDelegate::FinalResult result,
const std::string& custom_message,
const GURL& learn_more_url);
// Accessors to simplify |dialog_status_| checking.
inline bool is_success() const {
......@@ -144,6 +147,13 @@ class ContentAnalysisDialog : public views::DialogDelegate,
return dialog_status_ == DeepScanningDialogStatus::PENDING;
}
bool has_custom_message() const { return !final_custom_message_.empty(); }
bool has_learn_more_url() const {
return !final_learn_more_url_.is_empty() &&
final_learn_more_url_.is_valid();
}
// Returns the side image's logo color depending on |dialog_status_|.
SkColor GetSideImageLogoColor() const;
......@@ -202,11 +212,14 @@ class ContentAnalysisDialog : public views::DialogDelegate,
// Returns the appropriate success message depending on |files_count_|.
base::string16 GetSuccessMessage() const;
base::string16 GetCustomMessage() const;
// Show the dialog. Sets |shown_| to true.
void Show();
void AcceptButtonCallback();
void CancelButtonCallback();
void LearnMoreLinkClickedCallback(const ui::Event& event);
// This callback used by DialogDelegate::SetCancelCallback and is used to
// ensure the auto-closing success dialog handles focus correctly.
......@@ -222,6 +235,7 @@ class ContentAnalysisDialog : public views::DialogDelegate,
DeepScanningSideIconImageView* side_icon_image_ = nullptr;
DeepScanningSideIconSpinnerView* side_icon_spinner_ = nullptr;
DeepScanningMessageView* message_ = nullptr;
views::Link* learn_more_link_ = nullptr;
bool shown_ = false;
......@@ -233,6 +247,8 @@ class ContentAnalysisDialog : public views::DialogDelegate,
// Used to show the appropriate message.
ContentAnalysisDelegate::FinalResult final_result_ =
ContentAnalysisDelegate::FinalResult::SUCCESS;
std::string final_custom_message_;
GURL final_learn_more_url_;
// Used to animate dialog height changes.
std::unique_ptr<views::BoundsAnimator> bounds_animator_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment