| // Copyright 2020 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_SECURE_CHANNEL_NEARBY_CONNECTION_BROKER_IMPL_H_ |
| #define CHROME_BROWSER_ASH_SECURE_CHANNEL_NEARBY_CONNECTION_BROKER_IMPL_H_ |
| |
| #include <memory> |
| #include <ostream> |
| |
| #include "base/containers/flat_map.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "chrome/browser/ash/secure_channel/nearby_connection_broker.h" |
| #include "chromeos/ash/services/nearby/public/mojom/nearby_connections.mojom.h" |
| #include "chromeos/ash/services/secure_channel/public/mojom/nearby_connector.mojom-shared.h" |
| #include "chromeos/ash/services/secure_channel/public/mojom/nearby_connector.mojom.h" |
| #include "chromeos/ash/services/secure_channel/public/mojom/secure_channel_types.mojom.h" |
| #include "chromeos/ash/services/secure_channel/util/histogram_util.h" |
| #include "mojo/public/cpp/bindings/shared_remote.h" |
| |
| namespace ash { |
| namespace secure_channel { |
| |
| class NearbyEndpointFinder; |
| |
| // NearbyConnectionBroker implementation which utilizes NearbyEndpointFinder to |
| // find an endpoint, then uses Nearby Connections to create and maintain a |
| // connection. The overall process consists of: |
| // (1) Finding an endpoint via NearbyEndpointFinder. |
| // (2) Requesting a connection using that endpoint. |
| // (3) Accepting a connection. |
| // (4) Exchanging messages over the connection. |
| // |
| // Deleting an instance of this class tears down any active connection and |
| // performs cleanup if necessary. |
| class NearbyConnectionBrokerImpl |
| : public NearbyConnectionBroker, |
| public ::nearby::connections::mojom::ConnectionLifecycleListener, |
| public ::nearby::connections::mojom::PayloadListener { |
| public: |
| class Factory { |
| public: |
| static std::unique_ptr<NearbyConnectionBroker> Create( |
| const std::vector<uint8_t>& bluetooth_public_address, |
| const std::vector<uint8_t>& eid, |
| NearbyEndpointFinder* endpoint_finder, |
| mojo::PendingReceiver<mojom::NearbyMessageSender> |
| message_sender_receiver, |
| mojo::PendingReceiver<mojom::NearbyFilePayloadHandler> |
| file_payload_handler_receiver, |
| mojo::PendingRemote<mojom::NearbyMessageReceiver> |
| message_receiver_remote, |
| mojo::PendingRemote<mojom::NearbyConnectionStateListener> |
| nearby_connection_state_listener, |
| const mojo::SharedRemote< |
| ::nearby::connections::mojom::NearbyConnections>& |
| nearby_connections, |
| base::OnceClosure on_connected_callback, |
| base::OnceClosure on_disconnected_callback, |
| std::unique_ptr<base::OneShotTimer> timer = |
| std::make_unique<base::OneShotTimer>()); |
| static void SetFactoryForTesting(Factory* test_factory); |
| |
| virtual ~Factory() = default; |
| |
| protected: |
| virtual std::unique_ptr<NearbyConnectionBroker> CreateInstance( |
| const std::vector<uint8_t>& bluetooth_public_address, |
| NearbyEndpointFinder* endpoint_finder, |
| mojo::PendingReceiver<mojom::NearbyMessageSender> |
| message_sender_receiver, |
| mojo::PendingReceiver<mojom::NearbyFilePayloadHandler> |
| file_payload_handler_receiver, |
| mojo::PendingRemote<mojom::NearbyMessageReceiver> |
| message_receiver_remote, |
| mojo::PendingRemote<mojom::NearbyConnectionStateListener> |
| nearby_connection_state_listener, |
| const mojo::SharedRemote< |
| ::nearby::connections::mojom::NearbyConnections>& |
| nearby_connections, |
| base::OnceClosure on_connected_callback, |
| base::OnceClosure on_disconnected_callback, |
| std::unique_ptr<base::OneShotTimer> timer) = 0; |
| }; |
| |
| ~NearbyConnectionBrokerImpl() override; |
| |
| private: |
| enum class ConnectionStatus { |
| kUninitialized, |
| kDiscoveringEndpoint, |
| kRequestingConnection, |
| kAcceptingConnection, |
| kWaitingForConnectionToBeAcceptedByRemoteDevice, |
| kConnected, |
| kDisconnecting, |
| kDisconnected, |
| }; |
| friend std::ostream& operator<<( |
| std::ostream& stream, |
| NearbyConnectionBrokerImpl::ConnectionStatus status); |
| |
| NearbyConnectionBrokerImpl( |
| const std::vector<uint8_t>& bluetooth_public_address, |
| const std::vector<uint8_t>& eid, |
| NearbyEndpointFinder* endpoint_finder, |
| mojo::PendingReceiver<mojom::NearbyMessageSender> message_sender_receiver, |
| mojo::PendingReceiver<mojom::NearbyFilePayloadHandler> |
| file_payload_handler_receiver, |
| mojo::PendingRemote<mojom::NearbyMessageReceiver> message_receiver_remote, |
| mojo::PendingRemote<mojom::NearbyConnectionStateListener> |
| nearby_connection_state_listener, |
| const mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections>& |
| nearby_connections, |
| base::OnceClosure on_connected_callback, |
| base::OnceClosure on_disconnected_callback, |
| std::unique_ptr<base::OneShotTimer> timer); |
| |
| void TransitionToStatus(ConnectionStatus connection_status); |
| void Disconnect(util::NearbyDisconnectionReason reason); |
| void TransitionToDisconnectedAndInvokeCallback(); |
| |
| void OnEndpointDiscovered( |
| const std::string& endpoint_id, |
| ::nearby::connections::mojom::DiscoveredEndpointInfoPtr info); |
| void OnDiscoveryFailure(::nearby::connections::mojom::Status status); |
| |
| void OnRequestConnectionResult(::nearby::connections::mojom::Status status); |
| void OnAcceptConnectionResult(::nearby::connections::mojom::Status status); |
| void OnSendPayloadResult(SendMessageCallback callback, |
| ::nearby::connections::mojom::Status status); |
| void OnDisconnectFromEndpointResult( |
| ::nearby::connections::mojom::Status status); |
| void OnConnectionStatusChangeTimeout(); |
| |
| void OnPayloadFileRegistered( |
| int64_t payload_id, |
| mojo::PendingRemote<mojom::FilePayloadListener> listener, |
| RegisterPayloadFileCallback callback, |
| ::nearby::connections::mojom::Status status); |
| void OnFilePayloadListenerDisconnect(int64_t payload_id); |
| void CleanUpPendingFileTransfers(); |
| |
| // NearbyConnectionBroker: |
| void OnMojoDisconnection() override; |
| |
| // mojom::NearbyMessageSender: |
| void SendMessage(const std::string& message, |
| SendMessageCallback callback) override; |
| |
| // mojom::NearbyFilePayloadHandler: |
| void RegisterPayloadFile( |
| int64_t payload_id, |
| mojom::PayloadFilesPtr payload_files, |
| mojo::PendingRemote<mojom::FilePayloadListener> listener, |
| RegisterPayloadFileCallback callback) override; |
| |
| // ::nearby::connections::mojom::ConnectionLifecycleListener: |
| void OnConnectionInitiated( |
| const std::string& endpoint_id, |
| ::nearby::connections::mojom::ConnectionInfoPtr info) override; |
| void OnConnectionAccepted(const std::string& endpoint_id) override; |
| void OnConnectionRejected(const std::string& endpoint_id, |
| ::nearby::connections::mojom::Status status) override; |
| void OnDisconnected(const std::string& endpoint_id) override; |
| void OnBandwidthChanged(const std::string& endpoint_id, |
| ::nearby::connections::mojom::Medium medium) override; |
| |
| // ::nearby::connections::mojom::PayloadListener: |
| void OnPayloadReceived( |
| const std::string& endpoint_id, |
| ::nearby::connections::mojom::PayloadPtr payload) override; |
| void OnPayloadTransferUpdate( |
| const std::string& endpoint_id, |
| ::nearby::connections::mojom::PayloadTransferUpdatePtr update) override; |
| |
| raw_ptr<NearbyEndpointFinder> endpoint_finder_; |
| mojo::SharedRemote<::nearby::connections::mojom::NearbyConnections> |
| nearby_connections_; |
| std::unique_ptr<base::OneShotTimer> timer_; |
| |
| mojo::Receiver<::nearby::connections::mojom::ConnectionLifecycleListener> |
| connection_lifecycle_listener_receiver_{this}; |
| mojo::Receiver<::nearby::connections::mojom::PayloadListener> |
| payload_listener_receiver_{this}; |
| |
| ConnectionStatus connection_status_ = ConnectionStatus::kUninitialized; |
| |
| // Starts empty, then set in OnEndpointDiscovered(). |
| std::string remote_endpoint_id_; |
| |
| // Starts as false and changes to true when WebRTC upgrade occurs. |
| bool has_upgraded_to_webrtc_ = false; |
| |
| // Whether or not a metric has been logged to note that a metric has been |
| // logged indicated that Disconnect() was called before a WebRTC upgrade |
| // occurred. |
| bool has_recorded_no_webrtc_metric_ = false; |
| |
| // Starts as false; set to true in OnConnectionInitiated() and back to false |
| // in OnDisconnected(). |
| bool need_to_disconnect_endpoint_ = false; |
| |
| // Starts as null; set in OnConnectionAccepted(). |
| base::Time time_when_connection_accepted_; |
| |
| bool has_disconnect_reason_been_logged_ = false; |
| |
| // Listeners for file payloads registered via RegisterPayloadFile(), keyed by |
| // payload ID. |
| base::flat_map<int64_t, mojo::Remote<mojom::FilePayloadListener>> |
| file_payload_listeners_; |
| // TaskRunner to close received payload files. |
| const scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| |
| base::WeakPtrFactory<NearbyConnectionBrokerImpl> weak_ptr_factory_{this}; |
| }; |
| |
| std::ostream& operator<<(std::ostream& stream, |
| NearbyConnectionBrokerImpl::ConnectionStatus status); |
| |
| } // namespace secure_channel |
| } // namespace ash |
| |
| #endif // CHROME_BROWSER_ASH_SECURE_CHANNEL_NEARBY_CONNECTION_BROKER_IMPL_H_ |