// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef DEVICE_FIDO_FIDO_DEVICE_DISCOVERY_H_ #define DEVICE_FIDO_FIDO_DEVICE_DISCOVERY_H_ #include #include #include #include #include #include #include "base/bind.h" #include "base/component_export.h" #include "base/memory/weak_ptr.h" #include "base/strings/string_piece.h" #include "device/fido/fido_discovery_base.h" #include "device/fido/fido_transport_protocol.h" namespace device { class FidoDevice; class FidoDeviceAuthenticator; class COMPONENT_EXPORT(DEVICE_FIDO) FidoDeviceDiscovery : public FidoDiscoveryBase { public: // EventStream is an unbuffered pipe that can be passed around and late-bound // to the receiver. template class EventStream { public: using Callback = base::RepeatingCallback; // New returns a callback for writing events, and ownership of an // |EventStream| that can be connected to in order to receive the events. // The callback may outlive the |EventStream|. Any events written when // either the |EventStream| has been deleted, or not yet connected, are // dropped. static std::pair>> New() { auto stream = std::make_unique>(); auto cb = base::BindRepeating(&EventStream::Transmit, stream->weak_factory_.GetWeakPtr()); return std::make_pair(std::move(cb), std::move(stream)); } void Connect(Callback connection) { connection_ = std::move(connection); } private: void Transmit(T t) { if (connection_) { connection_.Run(std::move(t)); } } Callback connection_; base::WeakPtrFactory> weak_factory_{this}; }; enum class State { kIdle, kStarting, kRunning, kStopped, }; FidoDeviceDiscovery(const FidoDeviceDiscovery&) = delete; FidoDeviceDiscovery& operator=(const FidoDeviceDiscovery&) = delete; ~FidoDeviceDiscovery() override; bool is_start_requested() const { return state_ != State::kIdle; } bool is_running() const { return state_ == State::kRunning; } std::vector GetAuthenticatorsForTesting(); std::vector GetAuthenticatorsForTesting() const; FidoDeviceAuthenticator* GetAuthenticatorForTesting( base::StringPiece authenticator_id); // FidoDiscoveryBase: void Start() override; bool MaybeStop() override; protected: explicit FidoDeviceDiscovery(FidoTransportProtocol transport); void NotifyDiscoveryStarted(bool success); // Convenience method that adds a FidoDeviceAuthenticator with the given // |device|. bool AddDevice(std::unique_ptr device); bool AddAuthenticator(std::unique_ptr authenticator); bool RemoveDevice(base::StringPiece device_id); FidoDeviceAuthenticator* GetAuthenticator(base::StringPiece authenticator_id); // Subclasses should implement this to actually start the discovery when it is // requested. // // The implementation should asynchronously invoke NotifyDiscoveryStarted when // the discovery is s tarted. virtual void StartInternal() = 0; // Map of ID to authenticator. It is a guarantee to subclasses that the ID of // the authenticator equals the ID of the device. std::map, std::less<>> authenticators_; private: void NotifyAuthenticatorAdded(FidoAuthenticator* authenticator); void NotifyAuthenticatorRemoved(FidoAuthenticator* authenticator); State state_ = State::kIdle; base::WeakPtrFactory weak_factory_{this}; }; } // namespace device #endif // DEVICE_FIDO_FIDO_DEVICE_DISCOVERY_H_