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/host/client_session.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/base/capabilities.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "remoting/base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/audio_encoder.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/audio_encoder_opus.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/audio_encoder_verbatim.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_encoder.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_encoder_verbatim.h" 178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "remoting/codec/video_encoder_vpx.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/audio_capturer.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/audio_scheduler.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/desktop_environment.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "remoting/host/host_extension_session.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/input_injector.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/screen_controls.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/screen_resolution.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/video_scheduler.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/control.pb.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/event.pb.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/client_stub.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/clipboard_thread_proxy.h" 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "remoting/protocol/pairing_registry.h" 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Default DPI to assume for old clients that use notifyClientDimensions. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kDefaultDPI = 96; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClientSession::ClientSession( 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventHandler* event_handler, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner, 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner, 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<protocol::ConnectionToClient> connection, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DesktopEnvironmentFactory* desktop_environment_factory, 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& max_duration, 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<protocol::PairingRegistry> pairing_registry, 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::vector<HostExtension*>& extensions) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : event_handler_(event_handler), 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_(connection.Pass()), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_jid_(connection_->session()->jid()), 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_environment_factory_(desktop_environment_factory), 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_tracker_(&host_input_filter_), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remote_input_filter_(&input_tracker_), 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mouse_clamping_filter_(&remote_input_filter_), 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) disable_input_filter_(mouse_clamping_filter_.input_filter()), 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_clipboard_filter_(clipboard_echo_filter_.host_filter()), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_input_filter_(&disable_input_filter_), 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_clipboard_filter_(&disable_clipboard_filter_), 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_clipboard_factory_(clipboard_echo_filter_.client_filter()), 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_duration_(max_duration), 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_task_runner_(audio_task_runner), 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_task_runner_(input_task_runner), 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_capture_task_runner_(video_capture_task_runner), 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_encode_task_runner_(video_encode_task_runner), 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_task_runner_(network_task_runner), 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ui_task_runner_(ui_task_runner), 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pairing_registry_(pairing_registry), 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pause_video_(false), 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lossless_video_encode_(false), 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci lossless_video_color_(false), 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_(this) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->SetEventHandler(this); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sergeyu): Currently ConnectionToClient expects stubs to be 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set before channels are connected. Make it possible to set stubs 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // later and set them only when connection is authenticated. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->set_clipboard_stub(&auth_clipboard_filter_); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->set_host_stub(this); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->set_input_stub(&auth_input_filter_); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |auth_*_filter_|'s states reflect whether the session is authenticated. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_input_filter_.set_enabled(false); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_clipboard_filter_.set_enabled(false); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Create a manager for the configured extensions, if any. 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extension_manager_.reset(new HostExtensionSessionManager(extensions, this)); 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // LocalInputMonitorWin filters out an echo of the injected input before it 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // reaches |remote_input_filter_|. 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_input_filter_.SetExpectLocalEcho(false); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // defined(OS_WIN) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ClientSession::~ClientSession() { 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(CalledOnValidThread()); 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!audio_scheduler_.get()); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!desktop_environment_); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!input_injector_); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!screen_controls_); 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!video_scheduler_.get()); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_.reset(); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClientSession::NotifyClientResolution( 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const protocol::ClientResolution& resolution) { 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // TODO(sergeyu): Move these checks to protocol layer. 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!resolution.has_dips_width() || !resolution.has_dips_height() || 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) resolution.dips_width() < 0 || resolution.dips_height() < 0 || 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) resolution.width() <= 0 || resolution.height() <= 0) { 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG(ERROR) << "Received invalid ClientResolution message."; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "Received ClientResolution (dips_width=" 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << resolution.dips_width() << ", dips_height=" 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << resolution.dips_height() << ")"; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!screen_controls_) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScreenResolution client_resolution( 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) webrtc::DesktopSize(resolution.dips_width(), resolution.dips_height()), 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) webrtc::DesktopVector(kDefaultDPI, kDefaultDPI)); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Try to match the client's resolution. 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) screen_controls_->SetScreenResolution(client_resolution); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::ControlVideo(const protocol::VideoControl& video_control) { 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Note that |video_scheduler_| may be NULL, depending upon whether extensions 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // choose to wrap or "steal" the video capturer or encoder. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (video_control.has_enable()) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Received VideoControl (enable=" 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << video_control.enable() << ")"; 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pause_video_ = !video_control.enable(); 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (video_scheduler_.get()) 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_->Pause(pause_video_); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (video_control.has_lossless_encode()) { 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) VLOG(1) << "Received VideoControl (lossless_encode=" 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << video_control.lossless_encode() << ")"; 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lossless_video_encode_ = video_control.lossless_encode(); 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (video_scheduler_.get()) 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_->SetLosslessEncode(lossless_video_encode_); 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (video_control.has_lossless_color()) { 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) VLOG(1) << "Received VideoControl (lossless_color=" 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << video_control.lossless_color() << ")"; 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lossless_video_color_ = video_control.lossless_color(); 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (video_scheduler_.get()) 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_->SetLosslessColor(lossless_video_color_); 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) { 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (audio_control.has_enable()) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Received AudioControl (enable=" 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << audio_control.enable() << ")"; 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (audio_scheduler_.get()) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_scheduler_->Pause(!audio_control.enable()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ClientSession::SetCapabilities( 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const protocol::Capabilities& capabilities) { 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Ignore all the messages but the 1st one. 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (client_capabilities_) { 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(WARNING) << "protocol::Capabilities has been received already."; 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Compute the set of capabilities supported by both client and host. 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client_capabilities_ = make_scoped_ptr(new std::string()); 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (capabilities.has_capabilities()) 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *client_capabilities_ = capabilities.capabilities(); 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) capabilities_ = IntersectCapabilities(*client_capabilities_, 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) host_capabilities_); 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extension_manager_->OnNegotiatedCapabilities( 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) connection_->client_stub(), capabilities_); 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) VLOG(1) << "Client capabilities: " << *client_capabilities_; 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Calculate the set of capabilities enabled by both client and host and 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // pass it to the desktop environment if it is available. 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) desktop_environment_->SetCapabilities(capabilities_); 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ClientSession::RequestPairing( 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const protocol::PairingRequest& pairing_request) { 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (pairing_registry_.get() && pairing_request.has_client_name()) { 204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protocol::PairingRegistry::Pairing pairing = 205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pairing_registry_->CreatePairing(pairing_request.client_name()); 206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protocol::PairingResponse pairing_response; 2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pairing_response.set_client_id(pairing.client_id()); 2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pairing_response.set_shared_secret(pairing.shared_secret()); 209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) connection_->client_stub()->SetPairingResponse(pairing_response); 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 213c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid ClientSession::DeliverClientMessage( 214c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch const protocol::ExtensionMessage& message) { 21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (message.has_type()) { 21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (message.type() == "test-echo") { 21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) protocol::ExtensionMessage reply; 21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) reply.set_type("test-echo-reply"); 21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (message.has_data()) 22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) reply.set_data(message.data().substr(0, 16)); 22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) connection_->client_stub()->DeliverHostMessage(reply); 22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (message.type() == "gnubby-auth") { 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (gnubby_auth_handler_) { 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gnubby_auth_handler_->DeliverClientMessage(message.data()); 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HOST_LOG << "gnubby auth is not enabled"; 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!extension_manager_->OnExtensionMessage(message)) 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG(INFO) << "Unexpected message received: " 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << message.type() << ": " << message.data(); 23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 238c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 239c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ClientSession::OnConnectionAuthenticating( 241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch protocol::ConnectionToClient* connection) { 242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch event_handler_->OnSessionAuthenticating(this); 243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::OnConnectionAuthenticated( 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol::ConnectionToClient* connection) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(connection_.get(), connection); 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!audio_scheduler_.get()); 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!desktop_environment_); 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!input_injector_); 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!screen_controls_); 253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!video_scheduler_.get()); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_input_filter_.set_enabled(true); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_clipboard_filter_.set_enabled(true); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clipboard_echo_filter_.set_client_stub(connection_->client_stub()); 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mouse_clamping_filter_.set_video_stub(connection_->video_stub()); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (max_duration_ > base::TimeDelta()) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(simonmorris): Let Disconnect() tell the client that the 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // disconnection was caused by the session exceeding its maximum duration. 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_duration_timer_.Start(FROM_HERE, max_duration_, 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, &ClientSession::DisconnectSession); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Disconnect the session if the connection was rejected by the host. 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!event_handler_->OnSessionAuthenticated(this)) { 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DisconnectSession(); 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Create the desktop environment. Drop the connection if it could not be 275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // created for any reason (for instance the curtain could not initialize). 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_environment_ = 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci desktop_environment_factory_->Create(weak_factory_.GetWeakPtr()); 278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!desktop_environment_) { 279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DisconnectSession(); 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Collate the set of capabilities to offer the client, if it supports them. 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci host_capabilities_ = desktop_environment_->GetCapabilities(); 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!host_capabilities_.empty()) 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci host_capabilities_.append(" "); 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci host_capabilities_.append(extension_manager_->GetCapabilities()); 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the object that controls the screen resolution. 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) screen_controls_ = desktop_environment_->CreateScreenControls(); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Create the event executor. 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_injector_ = desktop_environment_->CreateInputInjector(); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Connect the host clipboard and input stubs. 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_input_filter_.set_input_stub(input_injector_.get()); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) clipboard_echo_filter_.set_host_stub(input_injector_.get()); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an AudioScheduler if audio is enabled, to pump audio samples. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (connection_->session()->config().is_audio_enabled()) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioEncoder> audio_encoder = 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateAudioEncoder(connection_->session()->config()); 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_scheduler_ = new AudioScheduler( 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_task_runner_, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_task_runner_, 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_environment_->CreateAudioCapturer(), 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_encoder.Pass(), 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->audio_stub()); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Create a GnubbyAuthHandler to proxy gnubbyd messages. 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gnubby_auth_handler_ = desktop_environment_->CreateGnubbyAuthHandler( 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) connection_->client_stub()); 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ClientSession::OnConnectionChannelsConnected( 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protocol::ConnectionToClient* connection) { 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(connection_.get(), connection); 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Negotiate capabilities with the client. 3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "Host capabilities: " << host_capabilities_; 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protocol::Capabilities capabilities; 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci capabilities.set_capabilities(host_capabilities_); 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci connection_->client_stub()->SetCapabilities(capabilities); 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Start the event executor. 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) input_injector_->Start(CreateClipboardProxy()); 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetDisableInputs(false); 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Start recording video. 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ResetVideoPipeline(); 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Start recording audio. 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (connection_->session()->config().is_audio_enabled()) 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_scheduler_->Start(); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the event handler that all our channels are now connected. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_handler_->OnSessionChannelsConnected(this); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::OnConnectionClosed( 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol::ConnectionToClient* connection, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol::ErrorCode error) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(connection_.get(), connection); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ignore any further callbacks. 3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_.InvalidateWeakPtrs(); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the client never authenticated then the session failed. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!auth_input_filter_.enabled()) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_handler_->OnSessionAuthenticationFailed(this); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Block any further input events from the client. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(wez): Fix ChromotingHost::OnSessionClosed not to check our 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is_authenticated(), so that we can disable |auth_*_filter_| here. 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_input_filter_.set_enabled(false); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_clipboard_filter_.set_enabled(false); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that any pressed keys or buttons are released. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_tracker_.ReleaseAll(); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Stop components access the client, audio or video stubs, which are no 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // longer valid once ConnectionToClient calls OnConnectionClosed(). 367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (audio_scheduler_.get()) { 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_scheduler_->Stop(); 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_scheduler_ = NULL; 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (video_scheduler_.get()) { 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_scheduler_->Stop(); 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_scheduler_ = NULL; 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_clipboard_factory_.InvalidateWeakPtrs(); 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_injector_.reset(); 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) screen_controls_.reset(); 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_environment_.reset(); 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Notify the ChromotingHost that this client is disconnected. 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sergeyu): Log failure reason? 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_handler_->OnSessionClosed(this); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::OnSequenceNumberUpdated( 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol::ConnectionToClient* connection, int64 sequence_number) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(connection_.get(), connection); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (video_scheduler_.get()) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video_scheduler_->UpdateSequenceNumber(sequence_number); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::OnRouteChange( 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol::ConnectionToClient* connection, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& channel_name, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const protocol::TransportRoute& route) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(connection_.get(), connection); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_handler_->OnSessionRouteChange(this, channel_name, route); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string& ClientSession::client_jid() const { 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return client_jid_; 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClientSession::DisconnectSession() { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(connection_.get()); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_duration_timer_.Stop(); 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This triggers OnConnectionClosed(), and the session may be destroyed 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as the result, so this call must be the last in this method. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->Disconnect(); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ClientSession::OnLocalMouseMoved(const webrtc::DesktopVector& position) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_input_filter_.LocalMouseMoved(position); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientSession::SetDisableInputs(bool disable_inputs) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (disable_inputs) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_tracker_.ReleaseAll(); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_input_filter_.set_enabled(!disable_inputs); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_clipboard_filter_.set_enabled(!disable_inputs); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ClientSession::ResetVideoPipeline() { 4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (video_scheduler_.get()) { 4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_->Stop(); 4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_ = NULL; 4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Create VideoEncoder and DesktopCapturer to match the session's video 4436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // channel configuration. 4446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<webrtc::DesktopCapturer> video_capturer = 4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci desktop_environment_->CreateVideoCapturer(); 4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_manager_->OnCreateVideoCapturer(&video_capturer); 4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<VideoEncoder> video_encoder = 4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateVideoEncoder(connection_->session()->config()); 4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_manager_->OnCreateVideoEncoder(&video_encoder); 4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Don't start the VideoScheduler if either capturer or encoder are missing. 4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!video_capturer || !video_encoder) 4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Create a VideoScheduler to pump frames from the capturer to the client. 4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_ = new VideoScheduler( 4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_capture_task_runner_, 4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_encode_task_runner_, 4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) network_task_runner_, 4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_capturer.Pass(), 4616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) desktop_environment_->CreateMouseCursorMonitor(), 4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_encoder.Pass(), 4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) connection_->client_stub(), 4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &mouse_clamping_filter_); 4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Apply video-control parameters to the new scheduler. 4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_->Pause(pause_video_); 4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_->SetLosslessEncode(lossless_video_encode_); 4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_->SetLosslessColor(lossless_video_color_); 4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Start capturing the screen. 4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_scheduler_->Start(); 4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ClientSession::SetGnubbyAuthHandlerForTesting( 476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GnubbyAuthHandler* gnubby_auth_handler) { 4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(CalledOnValidThread()); 478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gnubby_auth_handler_.reset(gnubby_auth_handler); 479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scoped_ptr<protocol::ClipboardStub>( 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new protocol::ClipboardThreadProxy( 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_clipboard_factory_.GetWeakPtr(), 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MessageLoopProxy::current())); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(sergeyu): Move this to SessionManager? 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<VideoEncoder> ClientSession::CreateVideoEncoder( 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const protocol::SessionConfig& config) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const protocol::ChannelConfig& video_config = config.video_config(); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) { 4978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return remoting::VideoEncoderVpx::CreateForVP8().PassAs<VideoEncoder>(); 498e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP9) { 499e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return remoting::VideoEncoderVpx::CreateForVP9().PassAs<VideoEncoder>(); 5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { 5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return scoped_ptr<VideoEncoder>(new remoting::VideoEncoderVerbatim()); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 504d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 5057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return scoped_ptr<VideoEncoder>(); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<AudioEncoder> ClientSession::CreateAudioEncoder( 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const protocol::SessionConfig& config) { 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const protocol::ChannelConfig& audio_config = config.audio_config(); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scoped_ptr<AudioEncoder>(new AudioEncoderVerbatim()); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (audio_config.codec == protocol::ChannelConfig::CODEC_OPUS) { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scoped_ptr<AudioEncoder>(new AudioEncoderOpus()); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 519d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 5207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return scoped_ptr<AudioEncoder>(); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 524