blob: 1661486adb6f9ea1796b54dc2f0f5706db2e0d93 [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_ASH_LOGIN_OOBE_QUICK_START_TARGET_DEVICE_BOOTSTRAP_CONTROLLER_H_
#define CHROME_BROWSER_ASH_LOGIN_OOBE_QUICK_START_TARGET_DEVICE_BOOTSTRAP_CONTROLLER_H_
#include <memory>
#include <string>
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "chrome/browser/ash/login/oobe_quick_start/connectivity/fido_assertion_info.h"
#include "chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker.h"
#include "chromeos/ash/services/nearby/public/mojom/quick_start_decoder_types.mojom.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
namespace ash::quick_start {
class TargetDeviceBootstrapController
: public TargetDeviceConnectionBroker::ConnectionLifecycleListener {
public:
explicit TargetDeviceBootstrapController(
std::unique_ptr<TargetDeviceConnectionBroker>
target_device_connection_broker);
TargetDeviceBootstrapController(TargetDeviceBootstrapController&) = delete;
TargetDeviceBootstrapController& operator=(TargetDeviceBootstrapController&) =
delete;
~TargetDeviceBootstrapController() override;
enum class Step {
NONE,
ERROR,
ADVERTISING,
QR_CODE_VERIFICATION,
PIN_VERIFICATION,
CONNECTED,
GAIA_CREDENTIALS,
CONNECTING_TO_WIFI,
CONNECTED_TO_WIFI,
TRANSFERRING_GOOGLE_ACCOUNT_DETAILS,
TRANSFERRED_GOOGLE_ACCOUNT_DETAILS,
};
enum class ErrorCode {
START_ADVERTISING_FAILED,
CONNECTION_REJECTED,
CONNECTION_CLOSED,
WIFI_CREDENTIALS_NOT_RECEIVED,
USER_VERIFICATION_FAILED,
GAIA_ASSERTION_NOT_RECEIVED,
};
using QRCodePixelData = std::vector<uint8_t>;
using Payload = absl::variant<absl::monostate, ErrorCode, QRCodePixelData>;
struct Status {
Status();
~Status();
Step step = Step::NONE;
Payload payload;
std::string ssid;
std::string password;
std::string fido_email;
};
class Observer : public base::CheckedObserver {
public:
virtual void OnStatusChanged(const Status& status) = 0;
protected:
~Observer() override = default;
};
void AddObserver(Observer* obs);
void RemoveObserver(Observer* obs);
void GetFeatureSupportStatusAsync(
TargetDeviceConnectionBroker::FeatureSupportStatusCallback callback);
// Returns the CryptAuth Instance ID of the connected remote device. Returns
// an empty string if no ID is available.
std::string GetPhoneInstanceId();
// This function would crash (if DCHECKs are on) in case there are existing
// valid weakptrs.
base::WeakPtr<TargetDeviceBootstrapController> GetAsWeakPtrForClient();
// TODO: Finalize api for frontend.
void StartAdvertising();
void StopAdvertising();
void MaybeCloseOpenConnections();
// A user may initiate Quick Start then have to download an update and reboot.
// This function persists necessary data and notifies the source device so
// Quick Start can resume where it left off after the reboot.
void PrepareForUpdate();
// TargetDeviceConnectionBroker::ConnectionLifecycleListener:
void OnPinVerificationRequested(const std::string& pin) override;
void OnQRCodeVerificationRequested(
const std::vector<uint8_t>& qr_code_data) override;
void OnConnectionAuthenticated(
base::WeakPtr<TargetDeviceConnectionBroker::AuthenticatedConnection>
authenticated_connection) override;
void OnConnectionRejected() override;
void OnConnectionClosed(
TargetDeviceConnectionBroker::ConnectionClosedReason reason) override;
std::string GetDiscoverableName();
void AttemptWifiCredentialTransfer();
void AttemptGoogleAccountTransfer();
private:
friend class TargetDeviceBootstrapControllerTest;
void NotifyObservers();
void OnStartAdvertisingResult(bool success);
void OnStopAdvertising();
void WaitForUserVerification(base::OnceClosure on_verification);
void OnUserVerificationResult(base::OnceClosure on_verification,
absl::optional<mojom::UserVerificationResponse>
user_verification_response);
// If the target device successfully receives an ack message, it prepares to
// automatically resume Quick Start after the update and closes the
// connection. If ack_successful is 'false', it closes the connection without
// preparing to automatically resume Quick Start after the update.
void OnNotifySourceOfUpdateResponse(bool ack_successful);
void OnWifiCredentialsReceived(
absl::optional<mojom::WifiCredentials> credentials);
void OnFidoAssertionReceived(absl::optional<FidoAssertionInfo> assertion);
std::unique_ptr<TargetDeviceConnectionBroker> connection_broker_;
std::string pin_;
// TODO: Should we enforce one observer at a time here too?
base::ObserverList<Observer> observers_;
Status status_;
base::WeakPtr<TargetDeviceConnectionBroker::AuthenticatedConnection>
authenticated_connection_;
int32_t session_id_;
base::WeakPtrFactory<TargetDeviceBootstrapController>
weak_ptr_factory_for_clients_{this};
base::WeakPtrFactory<TargetDeviceBootstrapController> weak_ptr_factory_{this};
};
} // namespace ash::quick_start
#endif // CHROME_BROWSER_ASH_LOGIN_OOBE_QUICK_START_TARGET_DEVICE_BOOTSTRAP_CONTROLLER_H_