blob: c46e9a6a3c2c8b04239adac0f587dc3dc51b2e35 [file]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_HOST_CLIENT_SESSION_H_
#define REMOTING_HOST_CLIENT_SESSION_H_
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "base/callback_list.h"
#include "base/functional/callback_forward.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/single_thread_task_runner.h"
#include "base/timer/timer.h"
#include "remoting/base/errors.h"
#include "remoting/base/local_session_policies_provider.h"
#include "remoting/base/session_policies.h"
#include "remoting/host/base/desktop_environment_options.h"
#include "remoting/host/host_experiment_session_plugin.h"
#include "remoting/host/peer_session.h"
#include "remoting/protocol/connection_to_client.h"
#include "remoting/protocol/errors.h"
#include "remoting/protocol/pairing_registry.h"
#include "remoting/protocol/session.h"
namespace remoting {
// A ClientSession keeps a reference to a connection to a client, and maintains
// per-client state.
class ClientSession : public protocol::Session::EventHandler,
public PeerSession::EventHandler {
public:
// Callback interface for passing events to the ChromotingHost.
class EventHandler {
public:
// Called after authentication has started.
virtual void OnSessionAuthenticating(ClientSession* client) = 0;
// Called after authentication has finished successfully.
virtual void OnSessionAuthenticated(ClientSession* client) = 0;
// Called after we've finished connecting all channels.
virtual void OnSessionChannelsConnected(ClientSession* client) = 0;
// Called after authentication has failed. Must not tear down this
// object. OnSessionClosed() is notified after this handler
// returns.
virtual void OnSessionAuthenticationFailed(ClientSession* client) = 0;
// Called after connection has failed or after the client closed it.
virtual void OnSessionClosed(ClientSession* client) = 0;
// Called on notification of a route change event, when a channel is
// connected.
virtual void OnSessionRouteChange(
ClientSession* client,
const std::string& channel_name,
const protocol::TransportRoute& route) = 0;
// Called when session policies are received. Returns nullopt if the session
// policies are valid; otherwise returns an error code, which will be used
// to close the session with.
virtual std::optional<ErrorCode> OnSessionPoliciesReceived(
const SessionPolicies& policies) = 0;
protected:
virtual ~EventHandler() {}
};
// `event_handler` and `peer_session_factory` must outlive `this`.
ClientSession(
EventHandler* event_handler,
std::unique_ptr<protocol::Session> session,
PeerSessionFactory* peer_session_factory,
const DesktopEnvironmentOptions& desktop_environment_options,
const LocalSessionPoliciesProvider* local_session_policies_provider);
ClientSession(const ClientSession&) = delete;
ClientSession& operator=(const ClientSession&) = delete;
~ClientSession() override;
PeerSession* peer_session() const { return peer_session_.get(); }
// PeerSession::EventHandler interface.
void OnSessionChannelsConnected() override;
void OnSessionClosed(protocol::ErrorCode error,
const std::string& error_details,
const SourceLocation& error_location) override;
void OnSessionRouteChange(const std::string& channel_name,
const protocol::TransportRoute& route) override;
const std::string& client_jid() const;
void DisconnectSession(ErrorCode error,
std::string_view error_details,
const SourceLocation& error_location);
void OnSessionServicesClientConnected(
mojo::PendingReceiver<mojom::ChromotingSessionServices> receiver);
// protocol::Session::EventHandler interface.
void OnSessionStateChange(protocol::Session::State state) override;
bool is_authenticated() const { return is_authenticated_; }
bool channels_connected() const { return channels_connected_; }
const SessionPolicies& effective_policies_for_tests() const {
return effective_policies_;
}
private:
friend class ClientSessionTest;
friend class ChromotingHostTest;
void OnConnectionAuthenticating();
void OnConnectionAuthenticated(const SessionPolicies* session_policies);
void OnLocalSessionPoliciesChanged(const SessionPolicies& new_policies);
raw_ptr<EventHandler> event_handler_;
// The DesktopEnvironmentOptions used to initialize DesktopEnvironment.
DesktopEnvironmentOptions desktop_environment_options_;
// Set to true if the client was authenticated successfully.
bool is_authenticated_ = false;
// Set to true after all data channels have been connected.
bool channels_connected_ = false;
// Factory to create `PeerSession` objects.
raw_ptr<PeerSessionFactory> peer_session_factory_;
// The signaling session.
std::unique_ptr<protocol::Session> session_;
// Object to control the peer session. It is created after AUTHENTICATED.
std::unique_ptr<PeerSession> peer_session_;
// True if ClientSession teardown has already begun. Prevents re-entrant
// execution of OnConnectionClosed() when callbacks fire during teardown.
bool is_closing_ = false;
std::string client_jid_;
HostExperimentSessionPlugin host_experiment_session_plugin_;
SessionPolicies effective_policies_;
raw_ptr<const LocalSessionPoliciesProvider> local_session_policies_provider_;
// If `effective_policies` does not come from local session policies, the
// subscription will be null and OnLocalSessionPoliciesChanged() will never
// be called.
base::CallbackListSubscription local_session_policy_update_subscription_;
std::vector<mojo::PendingReceiver<mojom::ChromotingSessionServices>>
pending_session_services_receivers_;
base::OneShotTimer max_duration_timer_;
SEQUENCE_CHECKER(sequence_checker_);
// Used to disable callbacks to `this` once DisconnectSession() has been
// called.
base::WeakPtrFactory<ClientSession> weak_factory_{this};
};
} // namespace remoting
#endif // REMOTING_HOST_CLIENT_SESSION_H_