1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
// 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.
#ifndef CHROME_BROWSER_ENTERPRISE_CONNECTORS_ANALYSIS_CONTENT_ANALYSIS_DIALOG_DELEGATE_H_
#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_ANALYSIS_CONTENT_ANALYSIS_DIALOG_DELEGATE_H_
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_base.h"
#include "chrome/browser/enterprise/connectors/analysis/content_analysis_views.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h"
#include "components/enterprise/connectors/core/common.h"
#include "content/public/browser/web_contents.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/window/dialog_delegate.h"
namespace views {
class BoundsAnimator;
class BoxLayoutView;
class Link;
class StyledLabel;
class TableLayoutView;
class Textarea;
} // namespace views
namespace enterprise_connectors {
// Implementation of `views::DialogDelegate` used to show a user the state of
// content analysis triggered by one of their action.
class ContentAnalysisDialogDelegate : public views::DialogDelegate,
public views::TextfieldController,
public ContentAnalysisBaseView::Delegate {
public:
// Enum used to represent what the dialog is currently showing.
enum class State {
// The dialog is shown with an explanation that the scan is being performed
// and that the result is pending.
PENDING,
// The dialog is shown with a short message indicating that the scan was a
// success and that the user may proceed with their upload, drag-and-drop or
// paste.
SUCCESS,
// The dialog is shown with a message indicating that the scan was a failure
// and that the user may not proceed with their upload, drag-and-drop or
// paste.
FAILURE,
// The dialog is shown with a message indicating that the scan was a
// failure, but that the user may proceed with their upload, drag-and-drop
// or paste if they want to.
WARNING,
};
ContentAnalysisDialogDelegate(
ContentAnalysisDelegateBase* delegate,
content::WebContents::Getter web_contents_getter,
bool is_cloud,
safe_browsing::DeepScanAccessPoint access_point,
int files_count);
~ContentAnalysisDialogDelegate() override;
// views::DialogDelegate:
std::u16string GetWindowTitle() const override;
bool ShouldShowCloseButton() const override;
views::Widget* GetWidget() override;
const views::Widget* GetWidget() const override;
ui::mojom::ModalType GetModalType() const override;
views::View* GetContentsView() override;
// ContentAnalysisBaseView::Delegate:
int GetTopImageId() const override;
ui::ColorId GetSideImageLogoColor() const override;
ui::ColorId GetSideImageBackgroundColor() const override;
bool is_result() const override;
// views::TextfieldController:
void ContentsChanged(views::Textfield* sender,
const std::u16string& new_contents) override;
// Accessors to simplify `dialog_state_` checking.
inline bool is_success() const { return dialog_state_ == State::SUCCESS; }
inline bool is_failure() const { return dialog_state_ == State::FAILURE; }
inline bool is_warning() const { return dialog_state_ == State::WARNING; }
inline bool is_pending() const { return dialog_state_ == State::PENDING; }
// Updates `final_result_` and `dialog_state_`.
void UpdateStateFromFinalResult(FinalContentAnalysisResult final_result);
// Update the appearance of the dialog. This will not do anything unless the
// dialog's state was changed by `UpdateStateFromFinalResult()` since the last
// `UpdateDialogAppearance()` call.
void UpdateDialogAppearance();
bool has_learn_more_url() const;
bool bypass_requires_justification() const;
// TODO(crbug.com/422111748): Change this to "private" after
// `ContentAnalysisDialogController` no longer inherits from this class.
protected:
// Helper functions to set/get various parts of the dialog depending on the
// values of `dialog_state_` and `delegate_base_`.
void SetupButtons();
std::u16string GetCancelButtonText() const;
std::u16string GetDialogMessage() const;
std::u16string GetPendingMessage() const;
std::u16string GetFailureMessage() const;
std::u16string GetWarningMessage() const;
std::u16string GetSuccessMessage() const;
std::u16string GetCustomMessage() const;
bool is_print_scan() const;
bool has_custom_message() const;
bool has_custom_message_ranges() const;
// Updates the views in the dialog to put them in the correct state for
// `dialog_state_`. This doesn't trigger the same events/resizes as
// UpdateDialog(), and doesn't require the presence of a widget. This is safe
// to use in the first GetContentsView() call, before the dialog is shown.
void UpdateViews();
// Resizes the already shown dialog to accommodate changes in its content.
void Resize(int height_to_add);
// Helper methods to get the admin message shown in dialog.
void AddLinksToDialogMessage();
void UpdateDialogMessage(std::u16string new_message);
// Helper methods to add views to `contents_view_` and `contents_layout_` that
// are not used for every state of the dialog.
void AddLearnMoreLinkToDialog();
void AddJustificationTextLabelToDialog();
void AddJustificationTextAreaToDialog();
void AddJustificationTextLengthToDialog();
void LearnMoreLinkClickedCallback(const ui::Event& event);
// Returns a newly created side icon. The created views are set to
// `side_icon_image_` and `side_icon_spinner_`.
std::unique_ptr<views::View> CreateSideIcon();
// Views above the buttons. `contents_view_` owns every other view.
raw_ptr<views::BoxLayoutView> contents_view_ = nullptr;
raw_ptr<ContentAnalysisTopImageView> image_ = nullptr;
raw_ptr<ContentAnalysisSideIconImageView> side_icon_image_ = nullptr;
raw_ptr<ContentAnalysisSideIconSpinnerView> side_icon_spinner_ = nullptr;
raw_ptr<views::StyledLabel> message_ = nullptr;
// The following views are also owned by `contents_view_`, but remain nullptr
// if they aren't required to be initialized.
raw_ptr<views::Link> learn_more_link_ = nullptr;
raw_ptr<views::Label> justification_text_label_ = nullptr;
raw_ptr<views::Textarea> bypass_justification_ = nullptr;
raw_ptr<views::Label> bypass_justification_text_length_ = nullptr;
// Table layout owned by `contents_view_`.
raw_ptr<views::TableLayoutView> contents_layout_ = nullptr;
// Used to animate dialog height changes.
std::unique_ptr<views::BoundsAnimator> bounds_animator_;
// Used to show the appropriate message.
FinalContentAnalysisResult final_result_;
// Used to show the appropriate dialog depending on the scan's status.
State dialog_state_ = State::PENDING;
// Should be owned by the parent of this class.
raw_ptr<ContentAnalysisDelegateBase> delegate_base_;
content::WebContents::Getter web_contents_getter_;
// True when performing a cloud-based content analysis, false when performing
// a locally based content analysis.
bool is_cloud_ = true;
// The access point that caused this dialog to open. This changes what text
// and top image are shown to the user.
safe_browsing::DeepScanAccessPoint access_point_;
// Indicates whether the scan being done is for files (files_count_>0) or for
// text (files_count_==0). This changes what text and top image are shown to
// the user.
int files_count_;
};
} // namespace enterprise_connectors
#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_ANALYSIS_CONTENT_ANALYSIS_DIALOG_DELEGATE_H_
|