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 23namespace remoting { 24 25using protocol::AuthenticationMethod; 26 27ChromotingClient::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 44ChromotingClient::~ChromotingClient() {} 45 46void ChromotingClient::SetProtocolConfigForTests( 47 scoped_ptr<protocol::CandidateSessionConfig> config) { 48 connection_.set_candidate_config(config.Pass()); 49} 50 51void 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 70void 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 92void ChromotingClient::SetPairingResponse( 93 const protocol::PairingResponse& pairing_response) { 94 DCHECK(task_runner_->BelongsToCurrentThread()); 95 96 user_interface_->SetPairingResponse(pairing_response); 97} 98 99void ChromotingClient::DeliverHostMessage( 100 const protocol::ExtensionMessage& message) { 101 DCHECK(task_runner_->BelongsToCurrentThread()); 102 103 user_interface_->DeliverHostMessage(message); 104} 105 106void ChromotingClient::InjectClipboardEvent( 107 const protocol::ClipboardEvent& event) { 108 DCHECK(task_runner_->BelongsToCurrentThread()); 109 110 user_interface_->GetClipboardStub()->InjectClipboardEvent(event); 111} 112 113void ChromotingClient::SetCursorShape( 114 const protocol::CursorShapeInfo& cursor_shape) { 115 DCHECK(task_runner_->BelongsToCurrentThread()); 116 117 user_interface_->GetCursorShapeStub()->SetCursorShape(cursor_shape); 118} 119 120void 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 134void ChromotingClient::OnConnectionReady(bool ready) { 135 VLOG(1) << "ChromotingClient::OnConnectionReady(" << ready << ")"; 136 user_interface_->OnConnectionReady(ready); 137} 138 139void 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 146void 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 156void 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