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
|
// Copyright 2023 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_PROFILES_PROFILE_PICKER_DICE_REAUTH_PROVIDER_H_
#define CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_PICKER_DICE_REAUTH_PROVIDER_H_
#include "base/scoped_observation.h"
#include "base/timer/timer.h"
#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
#include "chrome/browser/ui/views/profiles/profile_management_types.h"
#include "chrome/browser/ui/webui/signin/signin_ui_error.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "content/public/browser/web_contents_observer.h"
#include "google_apis/gaia/gaia_id.h"
struct CoreAccountInfo;
class ForceSigninVerifier;
class Profile;
class ProfilePickerWebContentsHost;
namespace content {
class WebContents;
}
// Enum used to recorded histogram results for the reauth step.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class ProfilePickerReauthResult {
kSuccess = 0,
kSuccessTokenAlreadyValid = 1,
kErrorUsedNewEmail = 2,
kErrorUsedOtherSignedInEmail = 3,
kTimeoutForceSigninVerifierCheck = 4,
kTimeoutSigninError = 5,
kMaxValue = kTimeoutSigninError
};
// This object handles the reauth of the main account of a Profile.
// The flow starts with the call to `SwitchToReauth()` and goes as follow:
// - Extract the primary account for which the reauth will be attempted.
// - Wait for the refresh tokens to be loaded.
// - Call to the ForceSigninVerifier to check the main account token status.
// - If the token is valid, there is no need to reauth, and we finish with
// success.
// - If it is not, we show the reauth gaia page and await for user to reauth.
// - Await a sign in event and a refersh token for the account that is being
// reauthed through `OnRefreshTokenUpdatedForAccount()`.
// - We finish the flow by replying to the callback based on the success of the
// last step (checking if the account that got reauthed matches with the
// original one).
class ProfilePickerDiceReauthProvider
: public signin::IdentityManager::Observer,
public content::WebContentsObserver {
public:
ProfilePickerDiceReauthProvider(
ProfilePickerWebContentsHost* host,
Profile* profile,
const GaiaId& gaia_id_to_reauth,
const std::string& email_to_reauth,
base::OnceCallback<void(bool, const ForceSigninUIError&)>
on_reauth_completed);
~ProfilePickerDiceReauthProvider() override;
ProfilePickerDiceReauthProvider(const ProfilePickerDiceReauthProvider&) =
delete;
ProfilePickerDiceReauthProvider& operator=(
const ProfilePickerDiceReauthProvider&) = delete;
content::WebContents* contents() const { return contents_.get(); }
// Start the reauth process.
void SwitchToReauth(StepSwitchFinishedCallback step_switch_callback);
// signin::IdentityManager::Observer:
void OnRefreshTokensLoaded() override;
void OnRefreshTokenUpdatedForAccount(
const CoreAccountInfo& account_info) override;
// content::WebContentsObserver:
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
private:
// Attempt to create the ForceSigninVerifier, refresh tokens should be loaded.
void TryCreateForceSigninVerifier();
// Timeout callback if the ForceSigninVerifier timed out. Finishing the flow
// with a failure.
void OnForceSigninVerifierTimeOut();
// Callback to the ForceSigninVerifier after fetching the tokens.
void OnTokenFetchComplete(bool token_is_valid);
// Display the reauth URL in `host_`.
void ShowReauth();
// Callback for the dice tab helper;
//
// When a successful sign in occurs.
void OnDiceSigninHeaderReceived();
// When a signin error occurs.
void OnSigninError(Profile* profile,
content::WebContents* web_contents,
const SigninUIError& error);
// Finish the reauth step on the Gaia side, and return to the caller
// through the `on_reauth_completed_`.
// Also records the result (success/errors) in a histogram.
void Finish(bool success, ProfilePickerReauthResult result);
const raw_ref<ProfilePickerWebContentsHost> host_;
raw_ref<Profile> profile_;
raw_ref<signin::IdentityManager> identity_manager_;
const GaiaId gaia_id_to_reauth_;
const std::string email_to_reauth_;
base::OnceCallback<void(bool, const ForceSigninUIError&)>
on_reauth_completed_;
// This callback will only return once we know whether the step should be
// shown or not.
StepSwitchFinishedCallback step_switch_callback_;
// Prevent `profile_` from being destroyed first.
std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive_;
// The web contents backed by `profile_`. This is used for displaying the
// reauth flow.
// Before displaying the reauth, this is used to display a loading screen
// while the ForceSigninVerifier is performing a network call.
std::unique_ptr<content::WebContents> contents_;
std::unique_ptr<ForceSigninVerifier> force_signin_verifier_;
bool signin_event_received_ = false;
// The timer is used for a timeout delay for the ForceSigninVerifier.
base::OneShotTimer timer_;
base::ScopedObservation<signin::IdentityManager,
signin::IdentityManager::Observer>
scoped_identity_manager_observation_{this};
};
#endif // CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_PICKER_DICE_REAUTH_PROVIDER_H_
|