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/rectangle_update_decoder.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 const ClientConfig& config, 29 ClientContext* client_context, 30 protocol::ConnectionToHost* connection, 31 ClientUserInterface* user_interface, 32 scoped_refptr<FrameConsumerProxy> frame_consumer, 33 scoped_ptr<AudioPlayer> audio_player) 34 : config_(config), 35 task_runner_(client_context->main_task_runner()), 36 connection_(connection), 37 user_interface_(user_interface), 38 host_capabilities_received_(false), 39 weak_factory_(this) { 40 rectangle_decoder_ = 41 new RectangleUpdateDecoder(client_context->main_task_runner(), 42 client_context->decode_task_runner(), 43 frame_consumer); 44 if (audio_player) { 45 audio_decode_scheduler_.reset(new AudioDecodeScheduler( 46 client_context->main_task_runner(), 47 client_context->audio_decode_task_runner(), 48 audio_player.Pass())); 49 } 50 } 51 52 ChromotingClient::~ChromotingClient() { 53 } 54 55 void ChromotingClient::Start( 56 SignalStrategy* signal_strategy, 57 scoped_ptr<protocol::TransportFactory> transport_factory) { 58 DCHECK(task_runner_->BelongsToCurrentThread()); 59 60 scoped_ptr<protocol::Authenticator> authenticator( 61 new protocol::NegotiatingClientAuthenticator( 62 config_.client_pairing_id, 63 config_.client_paired_secret, 64 config_.authentication_tag, 65 config_.fetch_secret_callback, 66 user_interface_->GetTokenFetcher(config_.host_public_key), 67 config_.authentication_methods)); 68 69 // Create a WeakPtr to ourself for to use for all posted tasks. 70 weak_ptr_ = weak_factory_.GetWeakPtr(); 71 72 connection_->Connect(signal_strategy, 73 config_.host_jid, 74 config_.host_public_key, 75 transport_factory.Pass(), 76 authenticator.Pass(), 77 this, 78 this, 79 this, 80 rectangle_decoder_.get(), 81 audio_decode_scheduler_.get()); 82 } 83 84 FrameProducer* ChromotingClient::GetFrameProducer() { 85 return rectangle_decoder_.get(); 86 } 87 88 ChromotingStats* ChromotingClient::GetStats() { 89 DCHECK(task_runner_->BelongsToCurrentThread()); 90 return rectangle_decoder_->GetStats(); 91 } 92 93 void ChromotingClient::SetCapabilities( 94 const protocol::Capabilities& capabilities) { 95 DCHECK(task_runner_->BelongsToCurrentThread()); 96 97 // Only accept the first |protocol::Capabilities| message. 98 if (host_capabilities_received_) { 99 LOG(WARNING) << "protocol::Capabilities has been received already."; 100 return; 101 } 102 103 host_capabilities_received_ = true; 104 if (capabilities.has_capabilities()) 105 host_capabilities_ = capabilities.capabilities(); 106 107 VLOG(1) << "Host capabilities: " << host_capabilities_; 108 109 // Calculate the set of capabilities enabled by both client and host and pass 110 // it to the webapp. 111 user_interface_->SetCapabilities( 112 IntersectCapabilities(config_.capabilities, host_capabilities_)); 113 } 114 115 void ChromotingClient::SetPairingResponse( 116 const protocol::PairingResponse& pairing_response) { 117 DCHECK(task_runner_->BelongsToCurrentThread()); 118 119 user_interface_->SetPairingResponse(pairing_response); 120 } 121 122 void ChromotingClient::DeliverHostMessage( 123 const protocol::ExtensionMessage& message) { 124 DCHECK(task_runner_->BelongsToCurrentThread()); 125 126 user_interface_->DeliverHostMessage(message); 127 } 128 129 void ChromotingClient::InjectClipboardEvent( 130 const protocol::ClipboardEvent& event) { 131 DCHECK(task_runner_->BelongsToCurrentThread()); 132 133 user_interface_->GetClipboardStub()->InjectClipboardEvent(event); 134 } 135 136 void ChromotingClient::SetCursorShape( 137 const protocol::CursorShapeInfo& cursor_shape) { 138 DCHECK(task_runner_->BelongsToCurrentThread()); 139 140 user_interface_->GetCursorShapeStub()->SetCursorShape(cursor_shape); 141 } 142 143 void ChromotingClient::OnConnectionState( 144 protocol::ConnectionToHost::State state, 145 protocol::ErrorCode error) { 146 DCHECK(task_runner_->BelongsToCurrentThread()); 147 VLOG(1) << "ChromotingClient::OnConnectionState(" << state << ")"; 148 149 if (state == protocol::ConnectionToHost::AUTHENTICATED) { 150 OnAuthenticated(); 151 } else if (state == protocol::ConnectionToHost::CONNECTED) { 152 OnChannelsConnected(); 153 } 154 user_interface_->OnConnectionState(state, error); 155 } 156 157 void ChromotingClient::OnConnectionReady(bool ready) { 158 VLOG(1) << "ChromotingClient::OnConnectionReady(" << ready << ")"; 159 user_interface_->OnConnectionReady(ready); 160 } 161 162 void ChromotingClient::OnAuthenticated() { 163 DCHECK(task_runner_->BelongsToCurrentThread()); 164 165 // Initialize the decoder. 166 rectangle_decoder_->Initialize(connection_->config()); 167 if (connection_->config().is_audio_enabled()) 168 audio_decode_scheduler_->Initialize(connection_->config()); 169 170 // Do not negotiate capabilities with the host if the host does not support 171 // them. 172 if (!connection_->config().SupportsCapabilities()) { 173 VLOG(1) << "The host does not support any capabilities."; 174 175 host_capabilities_received_ = true; 176 user_interface_->SetCapabilities(host_capabilities_); 177 } 178 } 179 180 void ChromotingClient::OnChannelsConnected() { 181 DCHECK(task_runner_->BelongsToCurrentThread()); 182 183 // Negotiate capabilities with the host. 184 if (connection_->config().SupportsCapabilities()) { 185 VLOG(1) << "Client capabilities: " << config_.capabilities; 186 187 protocol::Capabilities capabilities; 188 capabilities.set_capabilities(config_.capabilities); 189 connection_->host_stub()->SetCapabilities(capabilities); 190 } 191 } 192 193 } // namespace remoting 194