blob: f451c48afe7976a22a380bdf9635c3d879ddfe17 [file] [log] [blame]
// 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_BUBBLE_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_WEBID_ACCOUNT_SELECTION_BUBBLE_VIEW_H_
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/ui/views/webid/account_selection_view_base.h"
#include "components/image_fetcher/core/image_fetcher.h"
#include "content/public/browser/webid/identity_request_account.h"
#include "content/public/browser/webid/identity_request_dialog_controller.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/mojom/webid/federated_auth_request.mojom.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/layout/box_layout_view.h"
#include "ui/views/view.h"
namespace views {
class ImageButton;
class Label;
class Widget;
} // namespace views
namespace webid {
class AccountSelectionBubbleView;
class AccountSelectionBubbleDelegate : public views::BubbleDialogDelegate {
public:
AccountSelectionBubbleDelegate(
std::unique_ptr<AccountSelectionBubbleView> account_selection_bubble_view,
views::View* anchor_view);
~AccountSelectionBubbleDelegate() override;
AccountSelectionBubbleDelegate(const AccountSelectionBubbleDelegate&) =
delete;
AccountSelectionBubbleDelegate& operator=(
const AccountSelectionBubbleDelegate&) = delete;
// views::BubbleDialogDelegate overrides:
gfx::Rect GetBubbleBounds() override;
// TODO (kylixrd): Investigate removal of these overrides.
// views::WidgetDelegate overrides:
views::Widget* GetWidget() override;
const views::Widget* GetWidget() const override;
private:
AccountSelectionBubbleView* GetAccountSelectionView();
};
// Bubble dialog that is used in the FedCM flow. It creates a dialog with an
// account chooser for the user, and it changes the content of that dialog as
// user moves through the FedCM flow steps.
class AccountSelectionBubbleView : public views::BoxLayoutView,
public AccountSelectionViewBase {
METADATA_HEADER(AccountSelectionBubbleView, views::BoxLayoutView)
public:
AccountSelectionBubbleView(
const content::RelyingPartyData& rp_data,
const std::optional<std::u16string>& idp_title,
blink::mojom::RpContext rp_context,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
FedCmAccountSelectionView* owner);
~AccountSelectionBubbleView() override;
// AccountSelectionViewBase:
void ShowMultiAccountPicker(
const std::vector<IdentityRequestAccountPtr>& accounts,
const std::vector<IdentityProviderDataPtr>& idp_list,
const gfx::Image& rp_icon,
bool show_back_button) override;
void ShowVerifyingSheet(const IdentityRequestAccountPtr& account,
const std::u16string& title) override;
void ShowSingleAccountConfirmDialog(const IdentityRequestAccountPtr& account,
bool show_back_button) override;
void ShowFailureDialog(
const std::u16string& idp_for_display,
const content::IdentityProviderMetadata& idp_metadata) override;
void ShowErrorDialog(const std::u16string& idp_for_display,
const content::IdentityProviderMetadata& idp_metadata,
const std::optional<TokenError>& error) override;
void ShowRequestPermissionDialog(
const IdentityRequestAccountPtr& account) override;
std::string GetDialogTitle() const override;
std::optional<std::string> GetDialogSubtitle() const override;
std::u16string dialog_title() const { return title_; }
gfx::Rect GetBubbleBounds(gfx::Rect proposed_bubble_bounds);
private:
FRIEND_TEST_ALL_PREFIXES(AccountSelectionBubbleViewTest,
WebContentsLargeEnoughToFitDialog);
// Returns a View containing the logo of the identity provider.
std::unique_ptr<views::View> CreateHeaderView();
// Returns a pair <View, Button> where the first element is the View for
// single account chooser. This View contains the account information,
// disclosure text and a button for the user to confirm the selection. The
// second element is the button for the user to confirm the selection.
std::pair<std::unique_ptr<views::View>, views::MdTextButton*>
CreateSingleAccountChooser(const IdentityRequestAccountPtr& account);
// Adds a separator as well as a multiple account chooser. The chooser
// contains the info for each account in a button, so the user can pick an
// account. It also contains mismatch login URLs in the multiple IDP case.
void AddSeparatorAndMultipleAccountChooser(
const std::vector<IdentityRequestAccountPtr>& accounts,
const std::vector<IdentityProviderDataPtr>& idp_list);
// Adds the accounts provided to the given view. This method does not reorder
// the accounts, and assumes they are provided in the correct order.
void AddAccounts(const std::vector<IdentityRequestAccountPtr>& accounts,
views::View* accounts_content,
bool is_multi_idp);
// Invoked whenever the expandable account chooser is scrolled.
void OnExpandableAccountsScrolled();
// Returns a view containing a button for the user to login to an IDP for
// which there was a login status mismatch, to be used in the multiple account
// chooser case.
std::unique_ptr<views::View> CreateMultiIdpLoginRow(
const std::u16string& idp_for_display,
const IdentityProviderDataPtr& idp_data);
// Creates the "Use other account" button when showing a dialog with one IDP.
std::unique_ptr<views::View> CreateSingleIdpUseOtherAccountButton(
const content::IdentityProviderMetadata& idp_metadata,
const std::u16string& title,
int icon_margin);
// Updates the header title, the header icon visibility and the header back
// button visibility. `idp_image` is not empty when we need to set a header
// image based on the IDP. `should_circle_crop_header_icon` determines whether
// the icon passed should be cropped or not. Some icons like the RP icon are
// not meant to be cropped, and some icons like the badged account icon are
// cropped on the backend, so they should not be cropped here.
void UpdateHeader(const gfx::Image& idp_image,
const std::u16string& title,
const std::u16string& subtitle,
bool show_back_button,
bool should_circle_crop_header_icon);
// Removes all children except for `header_view_`.
void RemoveNonHeaderChildViews();
// Creates the "Choose an account" button, showing some IDP domains as well.
// Prioritizes showing any IDPs for which there was a login status mismatch.
std::unique_ptr<views::View> CreateChooseAnAccountButton(
const std::vector<std::u16string>& mismatch_idps,
const std::vector<std::u16string>& non_mismatch_idps);
// The current title for the dialog.
std::u16string title_;
// The current subtitle for the dialog.
std::u16string subtitle_;
// The relying party context to show in the title.
blink::mojom::RpContext rp_context_;
// View containing the logo of the identity provider and the title.
raw_ptr<views::View> header_view_ = nullptr;
// View containing the header IDP icon, if one needs to be used.
raw_ptr<BrandIconImageView> header_icon_view_ = nullptr;
// View containing the back button.
raw_ptr<views::ImageButton> back_button_ = nullptr;
// View containing the bubble title.
raw_ptr<views::Label> title_label_ = nullptr;
// View containing the bubble subtitle.
raw_ptr<views::Label> subtitle_label_ = nullptr;
// Used to ensure that callbacks are not run if the AccountSelectionBubbleView
// is destroyed.
base::WeakPtrFactory<AccountSelectionBubbleView> weak_ptr_factory_{this};
};
} // namespace webid
#endif // CHROME_BROWSER_UI_VIEWS_WEBID_ACCOUNT_SELECTION_BUBBLE_VIEW_H_