123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- // Copyright (c) 2012 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.
- #include "remoting/client/chromoting_client.h"
- #include <memory>
- #include <utility>
- #include "base/logging.h"
- #include "remoting/base/capabilities.h"
- #include "remoting/base/constants.h"
- #include "remoting/client/client_context.h"
- #include "remoting/client/client_user_interface.h"
- #include "remoting/protocol/authenticator.h"
- #include "remoting/protocol/connection_to_host.h"
- #include "remoting/protocol/host_stub.h"
- #include "remoting/protocol/ice_connection_to_host.h"
- #include "remoting/protocol/jingle_session_manager.h"
- #include "remoting/protocol/negotiating_client_authenticator.h"
- #include "remoting/protocol/session_config.h"
- #include "remoting/protocol/transport_context.h"
- #include "remoting/protocol/video_renderer.h"
- #include "remoting/protocol/webrtc_connection_to_host.h"
- #include "remoting/signaling/signaling_address.h"
- #include "remoting/signaling/signaling_id_util.h"
- #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
- namespace remoting {
- ChromotingClient::ChromotingClient(
- ClientContext* client_context,
- ClientUserInterface* user_interface,
- protocol::VideoRenderer* video_renderer,
- base::WeakPtr<protocol::AudioStub> audio_stream_consumer)
- : user_interface_(user_interface), video_renderer_(video_renderer) {
- DCHECK(client_context->main_task_runner()->BelongsToCurrentThread());
- audio_decode_task_runner_ = client_context->audio_decode_task_runner();
- audio_stream_consumer_ = audio_stream_consumer;
- }
- ChromotingClient::~ChromotingClient() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (signal_strategy_)
- signal_strategy_->RemoveListener(this);
- }
- void ChromotingClient::set_protocol_config(
- std::unique_ptr<protocol::CandidateSessionConfig> config) {
- DCHECK(!connection_)
- << "set_protocol_config() cannot be called after Start().";
- protocol_config_ = std::move(config);
- }
- void ChromotingClient::set_host_experiment_config(
- const std::string& experiment_config) {
- DCHECK(!connection_)
- << "set_host_experiment_config() cannot be called after Start().";
- host_experiment_sender_ =
- std::make_unique<HostExperimentSender>(experiment_config);
- }
- void ChromotingClient::SetConnectionToHostForTests(
- std::unique_ptr<protocol::ConnectionToHost> connection_to_host) {
- connection_ = std::move(connection_to_host);
- }
- void ChromotingClient::Start(
- SignalStrategy* signal_strategy,
- const protocol::ClientAuthenticationConfig& client_auth_config,
- scoped_refptr<protocol::TransportContext> transport_context,
- const std::string& host_jid,
- const std::string& capabilities) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!session_manager_); // Start must not be called more than once.
- host_jid_ = NormalizeSignalingId(host_jid);
- local_capabilities_ = capabilities;
- if (!protocol_config_) {
- protocol_config_ = protocol::CandidateSessionConfig::CreateDefault();
- }
- if (!connection_) {
- if (protocol_config_->webrtc_supported()) {
- LOG(FATAL) << "WebRTC is not supported.";
- } else {
- DCHECK(protocol_config_->ice_supported());
- connection_ = std::make_unique<protocol::IceConnectionToHost>();
- }
- }
- connection_->set_client_stub(this);
- connection_->set_clipboard_stub(this);
- connection_->set_video_renderer(video_renderer_);
- if (audio_stream_consumer_) {
- connection_->InitializeAudio(audio_decode_task_runner_,
- audio_stream_consumer_);
- } else {
- protocol_config_->DisableAudioChannel();
- }
- session_manager_ =
- std::make_unique<protocol::JingleSessionManager>(signal_strategy);
- session_manager_->set_protocol_config(std::move(protocol_config_));
- client_auth_config_ = client_auth_config;
- transport_context_ = transport_context;
- signal_strategy_ = signal_strategy;
- signal_strategy_->AddListener(this);
- switch (signal_strategy_->GetState()) {
- case SignalStrategy::CONNECTING:
- // Nothing to do here. Just need to wait until |signal_strategy_| becomes
- // connected.
- break;
- case SignalStrategy::CONNECTED:
- StartConnection();
- break;
- case SignalStrategy::DISCONNECTED:
- signal_strategy_->Connect();
- break;
- }
- }
- void ChromotingClient::Close() {
- DCHECK(thread_checker_.CalledOnValidThread());
- connection_->Disconnect(protocol::OK);
- }
- void ChromotingClient::SetCapabilities(
- const protocol::Capabilities& capabilities) {
- DCHECK(thread_checker_.CalledOnValidThread());
- // Only accept the first |protocol::Capabilities| message.
- if (host_capabilities_received_) {
- LOG(WARNING) << "protocol::Capabilities has been received already.";
- return;
- }
- host_capabilities_received_ = true;
- if (capabilities.has_capabilities())
- host_capabilities_ = capabilities.capabilities();
- VLOG(1) << "Host capabilities: " << host_capabilities_;
- // Calculate the set of capabilities enabled by both client and host and pass
- // it to the webapp.
- user_interface_->SetCapabilities(
- IntersectCapabilities(local_capabilities_, host_capabilities_));
- }
- void ChromotingClient::SetPairingResponse(
- const protocol::PairingResponse& pairing_response) {
- DCHECK(thread_checker_.CalledOnValidThread());
- user_interface_->SetPairingResponse(pairing_response);
- }
- void ChromotingClient::DeliverHostMessage(
- const protocol::ExtensionMessage& message) {
- DCHECK(thread_checker_.CalledOnValidThread());
- user_interface_->DeliverHostMessage(message);
- }
- void ChromotingClient::SetVideoLayout(const protocol::VideoLayout& layout) {
- int num_video_tracks = layout.video_track_size();
- if (num_video_tracks < 1) {
- LOG(ERROR) << "Received VideoLayout message with 0 tracks.";
- return;
- }
- if (num_video_tracks > 2) {
- LOG(WARNING) << "Received VideoLayout message with " << num_video_tracks
- << " tracks. Only one track is supported.";
- }
- const protocol::VideoTrackLayout& track_layout = layout.video_track(0);
- int x_dpi = track_layout.has_x_dpi() ? track_layout.x_dpi() : kDefaultDpi;
- int y_dpi = track_layout.has_y_dpi() ? track_layout.y_dpi() : kDefaultDpi;
- if (x_dpi != y_dpi) {
- LOG(WARNING) << "Mismatched x,y dpi. x=" << x_dpi << " y=" << y_dpi;
- }
- webrtc::DesktopSize size_dips(track_layout.width(), track_layout.height());
- webrtc::DesktopSize size_px(size_dips.width() * x_dpi / kDefaultDpi,
- size_dips.height() * y_dpi / kDefaultDpi);
- user_interface_->SetDesktopSize(size_px, webrtc::DesktopVector(x_dpi, y_dpi));
- mouse_input_scaler_.set_input_size(size_px.width(), size_px.height());
- if (connection_->config().protocol() ==
- protocol::SessionConfig::Protocol::ICE) {
- mouse_input_scaler_.set_output_size(size_px.width(), size_px.height());
- } else {
- mouse_input_scaler_.set_output_size(size_dips.width(), size_dips.height());
- }
- }
- void ChromotingClient::SetTransportInfo(
- const protocol::TransportInfo& transport_info) {}
- void ChromotingClient::InjectClipboardEvent(
- const protocol::ClipboardEvent& event) {
- DCHECK(thread_checker_.CalledOnValidThread());
- user_interface_->GetClipboardStub()->InjectClipboardEvent(event);
- }
- void ChromotingClient::SetCursorShape(
- const protocol::CursorShapeInfo& cursor_shape) {
- DCHECK(thread_checker_.CalledOnValidThread());
- user_interface_->GetCursorShapeStub()->SetCursorShape(cursor_shape);
- }
- void ChromotingClient::SetKeyboardLayout(
- const protocol::KeyboardLayout& layout) {
- DCHECK(thread_checker_.CalledOnValidThread());
- user_interface_->GetKeyboardLayoutStub()->SetKeyboardLayout(layout);
- }
- void ChromotingClient::OnConnectionState(
- protocol::ConnectionToHost::State state,
- protocol::ErrorCode error) {
- DCHECK(thread_checker_.CalledOnValidThread());
- VLOG(1) << "ChromotingClient::OnConnectionState(" << state << ")";
- if (state == protocol::ConnectionToHost::CONNECTED) {
- OnChannelsConnected();
- }
- user_interface_->OnConnectionState(state, error);
- }
- void ChromotingClient::OnConnectionReady(bool ready) {
- VLOG(1) << "ChromotingClient::OnConnectionReady(" << ready << ")";
- user_interface_->OnConnectionReady(ready);
- }
- void ChromotingClient::OnRouteChanged(const std::string& channel_name,
- const protocol::TransportRoute& route) {
- VLOG(0) << "Using " << protocol::TransportRoute::GetTypeString(route.type)
- << " connection for " << channel_name << " channel";
- user_interface_->OnRouteChanged(channel_name, route);
- }
- void ChromotingClient::OnSignalStrategyStateChange(
- SignalStrategy::State state) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (state == SignalStrategy::CONNECTED) {
- VLOG(1) << "Connected as: " << signal_strategy_->GetLocalAddress().id();
- // After signaling has been connected we can try connecting to the host.
- if (connection_ &&
- connection_->state() == protocol::ConnectionToHost::INITIALIZING) {
- StartConnection();
- }
- } else if (state == SignalStrategy::DISCONNECTED) {
- VLOG(1) << "Signaling connection closed.";
- mouse_input_scaler_.set_input_stub(nullptr);
- connection_.reset();
- user_interface_->OnConnectionState(protocol::ConnectionToHost::FAILED,
- protocol::SIGNALING_ERROR);
- }
- }
- bool ChromotingClient::OnSignalStrategyIncomingStanza(
- const jingle_xmpp::XmlElement* stanza) {
- return false;
- }
- void ChromotingClient::StartConnection() {
- DCHECK(thread_checker_.CalledOnValidThread());
- auto session = session_manager_->Connect(
- SignalingAddress(host_jid_),
- std::make_unique<protocol::NegotiatingClientAuthenticator>(
- signal_strategy_->GetLocalAddress().id(), host_jid_,
- client_auth_config_));
- if (host_experiment_sender_) {
- session->AddPlugin(host_experiment_sender_.get());
- }
- connection_->Connect(std::move(session), transport_context_, this);
- }
- void ChromotingClient::OnChannelsConnected() {
- DCHECK(thread_checker_.CalledOnValidThread());
- // Negotiate capabilities with the host.
- VLOG(1) << "Client capabilities: " << local_capabilities_;
- protocol::Capabilities capabilities;
- capabilities.set_capabilities(local_capabilities_);
- connection_->host_stub()->SetCapabilities(capabilities);
- mouse_input_scaler_.set_input_stub(connection_->input_stub());
- }
- } // namespace remoting
|