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