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 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
|
// Copyright 2022 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_UI_VIEWS_WEBID_ACCOUNT_SELECTION_VIEW_BASE_H_
#define CHROME_BROWSER_UI_VIEWS_WEBID_ACCOUNT_SELECTION_VIEW_BASE_H_
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback_helpers.h"
#include "base/i18n/case_conversion.h"
#include "chrome/browser/ui/views/controls/hover_button.h"
#include "chrome/browser/ui/webid/account_selection_view.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/styled_label.h"
namespace network {
class SharedURLLoaderFactory;
} // namespace network
namespace webid {
class FedCmAccountSelectionView;
// The radius used for the corner of the "Continue as" button.
inline constexpr int kButtonRadius = 16;
// The fixed, total width of the bubble.
inline constexpr int kBubbleWidth = 375;
// The size of the icon of the identity provider in the bubble.
inline constexpr int kBubbleIdpIconSize = 20;
// The desired size of the icon for a "login to IDP" secondary view.
inline constexpr int kIdpLoginIconSize = 20;
// The desired size of the icon for the "Choose an account" button or the "sign
// in to IDP" button in the multi IDP UI.
inline constexpr int kMultiIdpIconSize = 20;
// The left margin of a multi IDP icon button.
inline constexpr int kMultiIdpIconLeftMargin = 8;
// The right margin of a multi IDP icon button.
inline constexpr int kMultiIdpIconRightMargin = 10;
// The size of the padding used at the top and bottom of the bubble.
inline constexpr int kTopBottomPadding = 4;
// The size of the horizontal padding between the bubble content and the edge of
// the bubble, as well as the horizontal padding between icons and text.
inline constexpr int kLeftRightPadding = 12;
// The size of the vertical padding for most elements in the bubble.
inline constexpr int kVerticalSpacing = 8;
// Vertical spacing for buttons in multi IDP.
inline constexpr int kMultiIdpVerticalSpacing = 4;
// The height of the progress bar shown when showing "Verifying...".
inline constexpr int kProgressBarHeight = 2;
// The size of the space between the right boundary of the WebContents and the
// right boundary of the bubble.
inline constexpr int kRightMargin = 40;
// The size of the space between the top boundary of the WebContents and the top
// boundary of the bubble.
inline constexpr int kTopMargin = 16;
// The size of the icon of the identity provider in the modal.
inline constexpr int kModalIdpIconSize = 32;
// The size of the icons when they are combined i.e. IDP icon + arrow icon + RP
// icon is shown at the same time in the modal.
inline constexpr int kModalCombinedIconSize = 20;
// The size of the horizontal padding for most elements in the modal.
inline constexpr int kModalHorizontalSpacing = 8;
// The size of the arrow icon.
inline constexpr int kArrowIconSize = 8;
// The size of the spinner used in place of the IDP icon while it is being
// fetched.
inline constexpr int kModalIconSpinnerSize = 28;
// The size of the spinner used in a button when the user clicks on an account
// row, continue button or use other account button.
inline constexpr int kModalButtonSpinnerSize = 20;
inline constexpr char kImageFetcherUmaClient[] = "FedCMAccountChooser";
class BrandIconImageView : public views::ImageView {
METADATA_HEADER(BrandIconImageView, views::ImageView)
public:
explicit BrandIconImageView(int image_size);
BrandIconImageView(const BrandIconImageView&) = delete;
BrandIconImageView& operator=(const BrandIconImageView&) = delete;
~BrandIconImageView() override;
// This method will crop the given `image` if `should_circle_crop` and will
// attempt to set it into the BrandIconImageView. Returns whether the image
// was successfully set or not.
bool SetBrandIconImage(const gfx::Image& image, bool should_circle_crop);
private:
int image_size_;
};
class AccountHoverButton : public HoverButton {
public:
AccountHoverButton(PressedCallback callback,
std::unique_ptr<views::View> icon_view,
const std::u16string& title,
const std::u16string& subtitle,
std::unique_ptr<views::View> secondary_view,
bool add_vertical_label_spacing,
const std::u16string& footer,
int button_position);
AccountHoverButton(const AccountHoverButton&) = delete;
AccountHoverButton& operator=(const AccountHoverButton&) = delete;
~AccountHoverButton() override = default;
// HoverButton
void StateChanged(ButtonState old_state) override;
void OnPressed(const ui::Event& event);
bool HasBeenClicked();
// Changes the opacity of elements in the button to appear disabled. Used when
// the button is disabled in the verifying sheet.
void SetDisabledOpacity();
bool HasDisabledOpacity();
// Should only be invoked when the button has a secondary view.
void ReplaceSecondaryViewWithSpinner();
// Used for testing.
void SetCallbackForTesting(PressedCallback callback);
private:
PressedCallback callback_;
// The order of this account button relative to other account buttons in
// the dialog (e.g. 0 is the topmost account, 1 the one below it, etc.). Used
// to record a metric when the button is clicked.
int button_position_;
bool has_spinner_{false};
bool is_appear_disabled_{false};
bool has_been_clicked_{false};
};
class AccountHoverButtonSecondaryView : public views::View {
public:
AccountHoverButtonSecondaryView();
AccountHoverButtonSecondaryView(const AccountHoverButtonSecondaryView&) =
delete;
AccountHoverButtonSecondaryView& operator=(
const AccountHoverButtonSecondaryView&) = delete;
~AccountHoverButtonSecondaryView() override = default;
void ReplaceWithSpinner();
void SetDisabledOpacity();
private:
raw_ptr<views::ImageView> arrow_image_view_{nullptr};
};
// Base class for interacting with FedCM account selection dialog.
class AccountSelectionViewBase {
public:
AccountSelectionViewBase(
FedCmAccountSelectionView* owner,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const content::RelyingPartyData& rp_data,
float device_scale_factor);
virtual ~AccountSelectionViewBase();
// Updates the FedCM dialog to show the "account picker" sheet.
// `rp_icon` is the RP icon to be displayed on the header of the dialog when
// there are multiple IdPs to select from.
virtual void ShowMultiAccountPicker(
const std::vector<IdentityRequestAccountPtr>& accounts,
const std::vector<IdentityProviderDataPtr>& idp_list,
const gfx::Image& rp_icon,
bool show_back_button) = 0;
// Updates the FedCM dialog to show the "verifying" sheet.
virtual void ShowVerifyingSheet(const IdentityRequestAccountPtr& account,
const std::u16string& title) = 0;
// Updates to show a single account. On widget mode, used when showing the
// account confirmation dialog after the user picks one of multiple accounts.
// On button mode, used for the user to pick the single account.
virtual void ShowSingleAccountConfirmDialog(
const IdentityRequestAccountPtr& account,
bool show_back_button) = 0;
// Updates the FedCM dialog to show the "failure" sheet.
virtual void ShowFailureDialog(
const std::u16string& idp_for_display,
const content::IdentityProviderMetadata& idp_metadata) = 0;
// Updates the FedCM dialog to show the "error" sheet.
virtual void ShowErrorDialog(
const std::u16string& idp_for_display,
const content::IdentityProviderMetadata& idp_metadata,
const std::optional<TokenError>& error) = 0;
// Updates the FedCM dialog to show the "request permission" sheet.
virtual void ShowRequestPermissionDialog(
const IdentityRequestAccountPtr& account) = 0;
// Gets the title of the dialog.
virtual std::string GetDialogTitle() const = 0;
// Gets the subtitle of the dialog, if any.
virtual std::optional<std::string> GetDialogSubtitle() const = 0;
protected:
void SetLabelProperties(views::Label* label);
// Returns a View containing information about an account: the picture for
// the account on the left, and information about the account on the right.
// |clickable_position| contains an int if and only if the account is a
// HoverButton, and in that case the number is the 0-based position of that
// account in the overall dialog.
std::unique_ptr<views::View> CreateAccountRow(
const IdentityRequestAccountPtr& account,
std::optional<int> clickable_position,
bool should_include_idp,
bool is_modal_dialog = false,
int additional_vertical_padding = 0,
std::optional<std::u16string> last_used_string = std::nullopt);
// Returns a StyledLabel containing a disclosure label. The label links to
// privacy policy and terms of service URLs, if available.
std::unique_ptr<views::StyledLabel> CreateDisclosureLabel(
const IdentityRequestAccountPtr& account);
// Gets the summary and description string of the error.
std::pair<std::u16string, std::u16string> GetErrorDialogText(
const std::optional<TokenError>& error,
const std::u16string& idp_for_display);
// Observes events on AccountSelectionBubbleView.
// Dangling when running Chromedriver's run_py_tests.py test suite.
// TODO(https://crbug.com/377803489): This is a real dangling pointer in
// production code. The subclasses of AccountSelectionViewBase also inherit
// (indirectly) from views::DialogDelegate, with owned_by_widget = true. This
// means that this class is owned by the widget, which in turn is owned by
// FedCmAccountSelectionView. The problem is that the widget uses
// NATIVE_WIDGET_OWNS_WIDGET ownership semantics and is closed via
// Widget::Close() which is asynchronous. ~FedCmAccountSelectionView() calls
// into FedCmAccountSelectionView::Close() which asynchronously closes the
// Widget. When the Widget is eventually destroyed, this class is destroyed,
// but that's after FedCmAccountSelectionView is destroyed.
raw_ptr<FedCmAccountSelectionView, DanglingUntriaged> owner_{nullptr};
// Relying party data to customize the dialog.
content::RelyingPartyData rp_data_;
// The device's scale factor.
float device_scale_factor_;
// Used to ensure that callbacks are not run if the AccountSelectionViewBase
// is destroyed.
base::WeakPtrFactory<AccountSelectionViewBase> weak_ptr_factory_{this};
};
} // namespace webid
#endif // CHROME_BROWSER_UI_VIEWS_WEBID_ACCOUNT_SELECTION_VIEW_BASE_H_
|