1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "remoting/client/chromoting_client.h" 6 7 #include "base/bind.h" 8 #include "remoting/base/capabilities.h" 9 #include "remoting/client/audio_decode_scheduler.h" 10 #include "remoting/client/audio_player.h" 11 #include "remoting/client/client_context.h" 12 #include "remoting/client/client_user_interface.h" 13 #include "remoting/client/video_renderer.h" 14 #include "remoting/proto/audio.pb.h" 15 #include "remoting/proto/video.pb.h" 16 #include "remoting/protocol/authentication_method.h" 17 #include "remoting/protocol/connection_to_host.h" 18 #include "remoting/protocol/host_stub.h" 19 #include "remoting/protocol/negotiating_client_authenticator.h" 20 #include "remoting/protocol/session_config.h" 21 #include "remoting/protocol/transport.h" 22 23 namespace remoting { 24 25 using protocol::AuthenticationMethod; 26 27 ChromotingClient::ChromotingClient( 28 ClientContext* client_context, 29 ClientUserInterface* user_interface, 30 VideoRenderer* video_renderer, 31 scoped_ptr<AudioPlayer> audio_player) 32 : task_runner_(client_context->main_task_runner()), 33 user_interface_(user_interface), 34 video_renderer_(video_renderer), 35 host_capabilities_received_(false) { 36 if (audio_player) { 37 audio_decode_scheduler_.reset(new AudioDecodeScheduler( 38 client_context->main_task_runner(), 39 client_context->audio_decode_task_runner(), 40 audio_player.Pass())); 41 } 42 } 43 44 ChromotingClient::~ChromotingClient() {} 45 46 void ChromotingClient::SetProtocolConfigForTests( 47 scoped_ptr<protocol::CandidateSessionConfig> config) { 48 connection_.set_candidate_config(config.Pass()); 49 } 50 51 void ChromotingClient::Start( 52 SignalStrategy* signal_strategy, 53 scoped_ptr<protocol::Authenticator> authenticator, 54 scoped_ptr<protocol::TransportFactory> transport_factory, 55 const std::string& host_jid, 56 const std::string& capabilities) { 57 DCHECK(task_runner_->BelongsToCurrentThread()); 58 59 local_capabilities_ = capabilities; 60 61 connection_.set_client_stub(this); 62 connection_.set_clipboard_stub(this); 63 connection_.set_video_stub(video_renderer_); 64 connection_.set_audio_stub(audio_decode_scheduler_.get()); 65 66 connection_.Connect(signal_strategy, transport_factory.Pass(), 67 authenticator.Pass(), host_jid, this); 68 } 69 70 void ChromotingClient::SetCapabilities( 71 const protocol::Capabilities& capabilities) { 72 DCHECK(task_runner_->BelongsToCurrentThread()); 73 74 // Only accept the first |protocol::Capabilities| message. 75 if (host_capabilities_received_) { 76 LOG(WARNING) << "protocol::Capabilities has been received already."; 77 return; 78 } 79 80 host_capabilities_received_ = true; 81 if (capabilities.has_capabilities()) 82 host_capabilities_ = capabilities.capabilities(); 83 84 VLOG(1) << "Host capabilities: " << host_capabilities_; 85 86 // Calculate the set of capabilities enabled by both client and host and pass 87 // it to the webapp. 88 user_interface_->SetCapabilities( 89 IntersectCapabilities(local_capabilities_, host_capabilities_)); 90 } 91 92 void ChromotingClient::SetPairingResponse( 93 const protocol::PairingResponse& pairing_response) { 94 DCHECK(task_runner_->BelongsToCurrentThread()); 95 96 user_interface_->SetPairingResponse(pairing_response); 97 } 98 99 void ChromotingClient::DeliverHostMessage( 100 const protocol::ExtensionMessage& message) { 101 DCHECK(task_runner_->BelongsToCurrentThread()); 102 103 user_interface_->DeliverHostMessage(message); 104 } 105 106 void ChromotingClient::InjectClipboardEvent( 107 const protocol::ClipboardEvent& event) { 108 DCHECK(task_runner_->BelongsToCurrentThread()); 109 110 user_interface_->GetClipboardStub()->InjectClipboardEvent(event); 111 } 112 113 void ChromotingClient::SetCursorShape( 114 const protocol::CursorShapeInfo& cursor_shape) { 115 DCHECK(task_runner_->BelongsToCurrentThread()); 116 117 user_interface_->GetCursorShapeStub()->SetCursorShape(cursor_shape); 118 } 119 120 void ChromotingClient::OnConnectionState( 121 protocol::ConnectionToHost::State state, 122 protocol::ErrorCode error) { 123 DCHECK(task_runner_->BelongsToCurrentThread()); 124 VLOG(1) << "ChromotingClient::OnConnectionState(" << state << ")"; 125 126 if (state == protocol::ConnectionToHost::AUTHENTICATED) { 127 OnAuthenticated(); 128 } else if (state == protocol::ConnectionToHost::CONNECTED) { 129 OnChannelsConnected(); 130 } 131 user_interface_->OnConnectionState(state, error); 132 } 133 134 void ChromotingClient::OnConnectionReady(bool ready) { 135 VLOG(1) << "ChromotingClient::OnConnectionReady(" << ready << ")"; 136 user_interface_->OnConnectionReady(ready); 137 } 138 139 void ChromotingClient::OnRouteChanged(const std::string& channel_name, 140 const protocol::TransportRoute& route) { 141 VLOG(0) << "Using " << protocol::TransportRoute::GetTypeString(route.type) 142 << " connection for " << channel_name << " channel"; 143 user_interface_->OnRouteChanged(channel_name, route); 144 } 145 146 void ChromotingClient::OnAuthenticated() { 147 DCHECK(task_runner_->BelongsToCurrentThread()); 148 149 // Initialize the decoder. 150 video_renderer_->Initialize(connection_.config()); 151 if (connection_.config().is_audio_enabled()) 152 audio_decode_scheduler_->Initialize(connection_.config()); 153 154 } 155 156 void ChromotingClient::OnChannelsConnected() { 157 DCHECK(task_runner_->BelongsToCurrentThread()); 158 159 // Negotiate capabilities with the host. 160 VLOG(1) << "Client capabilities: " << local_capabilities_; 161 162 protocol::Capabilities capabilities; 163 capabilities.set_capabilities(local_capabilities_); 164 connection_.host_stub()->SetCapabilities(capabilities); 165 } 166 167 } // namespace remoting 168