File: account_selection_view_base.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (261 lines) | stat: -rw-r--r-- 10,862 bytes parent folder | download | duplicates (3)
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_