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
|
// 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 CHROMEOS_ASH_COMPONENTS_OSAUTH_IMPL_AUTH_HUB_VECTOR_LIFECYCLE_H_
#define CHROMEOS_ASH_COMPONENTS_OSAUTH_IMPL_AUTH_HUB_VECTOR_LIFECYCLE_H_
#include <optional>
#include "base/component_export.h"
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "chromeos/ash/components/osauth/impl/auth_hub_common.h"
#include "chromeos/ash/components/osauth/public/auth_factor_engine.h"
#include "chromeos/ash/components/osauth/public/common_types.h"
namespace ash {
// This class manages inner lifecycle of the auth hub.
// Outer lifecycle includes switching between `AuthAttemptVector`s,
// basically a combination of `AccountId`+`AuthPurpose`.
// This class is re-created every time owning `AuthHub` changes mode,
// and receives initialized engines as parameter.
// Lifecycle is:
// * Call each engine's `StartAuthFlow` with auth vector, and wait for
// completion.
// * Notify `Owner` about available / failed auth factors.
// * Once attempt is canceled, execute a two-stage finish:
// 1. Clean-up substage
// 1.1 Call each engine's `CleanUp`, and wait for completion.
// 1.2 Notify `Owner` that attempt is cleaned up.
// 2.Shutdown substage
// 2.1 Call each engine's `StopAuthFlow`, and wait for completion.
// 2.2 Notify `Owner` that attempt is finished.
// `AuthHubVectorLifecycle` correctly handles attempt start/finish, even if
// request to start/finish was requested in the middle of ongoing start/finish
// sequence.
class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_OSAUTH) AuthHubVectorLifecycle
: public AuthFactorEngine::FactorEngineObserver {
public:
// Interface to interact with owning AuthHub:
class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_OSAUTH) Owner {
public:
virtual ~Owner();
virtual AuthFactorEngine::FactorEngineObserver* AsEngineObserver() = 0;
virtual void OnAttemptStarted(const AuthAttemptVector& attempt,
AuthFactorsSet available_factors,
AuthFactorsSet failed_factors) = 0;
virtual void OnAttemptCleanedUp(const AuthAttemptVector& attempt) = 0;
virtual void OnAttemptFinished(const AuthAttemptVector& attempt) = 0;
virtual void OnAttemptCancelled(const AuthAttemptVector& attempt) = 0;
virtual void OnIdle() = 0;
};
AuthHubVectorLifecycle(Owner* owner,
AuthHubMode mode,
const AuthEnginesMap& engines);
~AuthHubVectorLifecycle() override;
void StartAttempt(const AuthAttemptVector& vector);
void OnFactorInitialized(AshAuthFactor factor);
// Calling any of those those methods would trigger the same cleanup code path
// within this class. The difference is the `owner_` aka `AuthHub` method that
// we call at the end of the cleanup, indicating either that the flow has been
// shut down due to a request from the user to cancel the flow, or that the
// flow has been shut down due to a successful auth attempt.
void CancelAttempt();
void FinishAttempt();
bool IsIdle() const;
// AuthFactorEngine::FactorEngineObserver:
void OnFactorPresenceChecked(AshAuthFactor factor,
bool factor_present) override;
void OnFactorAttempt(AshAuthFactor factor) override;
void OnFactorAttemptResult(AshAuthFactor factor, bool success) override;
void OnPolicyChanged(AshAuthFactor factor) override;
void OnLockoutChanged(AshAuthFactor factor) override;
void OnFactorSpecificRestrictionsChanged(AshAuthFactor factor) override;
void OnCriticalError(AshAuthFactor factor) override;
void OnFactorCustomSignal(AshAuthFactor factor) override;
private:
enum class Stage {
kIdle,
kStartingAttempt,
kStarted,
kCleaningUpAttempt,
kFinishingAttempt,
};
// When an attempt is finished, or canceled after request form the user we
// start shutting the engines as part of
// `AuthHubVectorLifecycle::ShutdownAttempt`, We need to notify `Owner` (a.k.a
// AuthHub) that we have finished all necessary steps for the shutdown, and
// thus, when finishing or canceling an attempt, we need to make sure we are
// properly notifying `AuthHub`.
using OnShutdownAttemptNotifyOwner =
base::OnceCallback<void(const AuthAttemptVector&)>;
struct FactorAttemptState;
void StartForTargetAttempt();
void OnAttemptStartWatchdog();
void ProceedIfAllFactorsStarted();
void ShutdownAttempt(OnShutdownAttemptNotifyOwner on_shutdown_attempt);
void OnFactorCleanedUp(AshAuthFactor factor);
void OnAttemptCleanedUpWatchdog();
void FinishIfAllFactorsCleanedUp();
void OnFactorFinished(AshAuthFactor factor);
void OnAttemptFinishWatchdog();
void ProceedIfAllFactorsFinished();
void OnCancelAttempt(const AuthAttemptVector& current_attempt);
void OnFinishAttempt(const AuthAttemptVector& current_attempt);
Stage stage_ = Stage::kIdle;
std::optional<AuthAttemptVector> current_attempt_;
std::optional<AuthAttemptVector> target_attempt_;
std::optional<AuthAttemptVector> initializing_for_;
std::optional<AuthAttemptVector> last_started_attempt_;
AuthEnginesMap available_engines_;
base::flat_map<AshAuthFactor, FactorAttemptState> engines_;
base::OneShotTimer watchdog_;
raw_ptr<Owner> owner_;
OnShutdownAttemptNotifyOwner on_shutdown_attempt_;
base::WeakPtrFactory<AuthHubVectorLifecycle> weak_factory_{this};
};
} // namespace ash
#endif // CHROMEOS_ASH_COMPONENTS_OSAUTH_IMPL_AUTH_HUB_VECTOR_LIFECYCLE_H_
|