15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/client/chromoting_client.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/base/capabilities.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/client/audio_decode_scheduler.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/client/audio_player.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/client/client_context.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/client/client_user_interface.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "remoting/client/video_renderer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/audio.pb.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/video.pb.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/authentication_method.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/connection_to_host.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/protocol/host_stub.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/protocol/negotiating_client_authenticator.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/session_config.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/transport.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using protocol::AuthenticationMethod; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromotingClient::ChromotingClient( 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientContext* client_context, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientUserInterface* user_interface, 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VideoRenderer* video_renderer, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioPlayer> audio_player) 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : task_runner_(client_context->main_task_runner()), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_interface_(user_interface), 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) video_renderer_(video_renderer), 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch host_capabilities_received_(false) { 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (audio_player) { 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch audio_decode_scheduler_.reset(new AudioDecodeScheduler( 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch client_context->main_task_runner(), 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch client_context->audio_decode_task_runner(), 407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch audio_player.Pass())); 417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ChromotingClient::~ChromotingClient() {} 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromotingClient::SetProtocolConfigForTests( 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<protocol::CandidateSessionConfig> config) { 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) connection_.set_candidate_config(config.Pass()); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromotingClient::Start( 527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SignalStrategy* signal_strategy, 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<protocol::Authenticator> authenticator, 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<protocol::TransportFactory> transport_factory, 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& host_jid, 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& capabilities) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch local_capabilities_ = capabilities; 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch connection_.set_client_stub(this); 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch connection_.set_clipboard_stub(this); 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch connection_.set_video_stub(video_renderer_); 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch connection_.set_audio_stub(audio_decode_scheduler_.get()); 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch connection_.Connect(signal_strategy, transport_factory.Pass(), 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch authenticator.Pass(), host_jid, this); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ChromotingClient::SetCapabilities( 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const protocol::Capabilities& capabilities) { 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Only accept the first |protocol::Capabilities| message. 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (host_capabilities_received_) { 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(WARNING) << "protocol::Capabilities has been received already."; 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) host_capabilities_received_ = true; 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (capabilities.has_capabilities()) 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) host_capabilities_ = capabilities.capabilities(); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) VLOG(1) << "Host capabilities: " << host_capabilities_; 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Calculate the set of capabilities enabled by both client and host and pass 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // it to the webapp. 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_interface_->SetCapabilities( 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IntersectCapabilities(local_capabilities_, host_capabilities_)); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromotingClient::SetPairingResponse( 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const protocol::PairingResponse& pairing_response) { 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) user_interface_->SetPairingResponse(pairing_response); 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 99c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid ChromotingClient::DeliverHostMessage( 100c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch const protocol::ExtensionMessage& message) { 101c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK(task_runner_->BelongsToCurrentThread()); 102c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 103c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch user_interface_->DeliverHostMessage(message); 104c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 105c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromotingClient::InjectClipboardEvent( 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const protocol::ClipboardEvent& event) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_interface_->GetClipboardStub()->InjectClipboardEvent(event); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromotingClient::SetCursorShape( 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const protocol::CursorShapeInfo& cursor_shape) { 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_interface_->GetCursorShapeStub()->SetCursorShape(cursor_shape); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromotingClient::OnConnectionState( 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol::ConnectionToHost::State state, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol::ErrorCode error) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "ChromotingClient::OnConnectionState(" << state << ")"; 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (state == protocol::ConnectionToHost::AUTHENTICATED) { 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnAuthenticated(); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (state == protocol::ConnectionToHost::CONNECTED) { 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnChannelsConnected(); 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_interface_->OnConnectionState(state, error); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromotingClient::OnConnectionReady(bool ready) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "ChromotingClient::OnConnectionReady(" << ready << ")"; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_interface_->OnConnectionReady(ready); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ChromotingClient::OnRouteChanged(const std::string& channel_name, 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const protocol::TransportRoute& route) { 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(0) << "Using " << protocol::TransportRoute::GetTypeString(route.type) 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " connection for " << channel_name << " channel"; 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_interface_->OnRouteChanged(channel_name, route); 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ChromotingClient::OnAuthenticated() { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the decoder. 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch video_renderer_->Initialize(connection_.config()); 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (connection_.config().is_audio_enabled()) 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch audio_decode_scheduler_->Initialize(connection_.config()); 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ChromotingClient::OnChannelsConnected() { 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Negotiate capabilities with the host. 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "Client capabilities: " << local_capabilities_; 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protocol::Capabilities capabilities; 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci capabilities.set_capabilities(local_capabilities_); 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci connection_.host_stub()->SetCapabilities(capabilities); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 168