blob: 17f49b4f938948ffb428b31c0c3a0105864a6615 [file] [log] [blame]
[email protected]91e4b7f62012-01-25 23:23:021// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]44f60762011-03-23 12:13:352// 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/host/client_session.h"
6
[email protected]4fe827a2011-08-10 03:30:197#include <algorithm>
8
wez43ac2662015-06-10 18:22:299#include "base/command_line.h"
anujk.sharmabb802932015-05-05 21:57:2910#include "base/single_thread_task_runner.h"
11#include "base/thread_task_runner_handle.h"
[email protected]a5d181f2013-04-19 14:55:3712#include "remoting/base/capabilities.h"
[email protected]6f742dd02013-11-26 23:19:5013#include "remoting/base/logging.h"
[email protected]170cba42012-09-12 22:28:3914#include "remoting/codec/audio_encoder.h"
[email protected]a6ccb7722012-10-23 21:10:4315#include "remoting/codec/audio_encoder_opus.h"
[email protected]170cba42012-09-12 22:28:3916#include "remoting/codec/audio_encoder_verbatim.h"
17#include "remoting/codec/video_encoder.h"
[email protected]2149bef2012-10-18 03:26:5318#include "remoting/codec/video_encoder_verbatim.h"
[email protected]a43cfae2013-10-19 22:14:5419#include "remoting/codec/video_encoder_vpx.h"
[email protected]ce404ca2013-01-16 17:23:5320#include "remoting/host/audio_capturer.h"
sergeyu7bc87602015-02-13 20:33:2821#include "remoting/host/audio_pump.h"
sergeyu1afb35a12015-02-13 18:45:3022#include "remoting/host/desktop_capturer_proxy.h"
[email protected]170cba42012-09-12 22:28:3923#include "remoting/host/desktop_environment.h"
[email protected]399b4f62014-05-30 20:13:1524#include "remoting/host/host_extension_session.h"
[email protected]b0b72f112013-03-24 03:42:4225#include "remoting/host/input_injector.h"
sergeyu1afb35a12015-02-13 18:45:3026#include "remoting/host/mouse_shape_pump.h"
[email protected]231316a2013-03-25 06:01:1227#include "remoting/host/screen_controls.h"
[email protected]739e2802013-03-18 01:03:4828#include "remoting/host/screen_resolution.h"
sergeyu10ce97b2015-02-05 23:53:1429#include "remoting/host/video_frame_pump.h"
[email protected]50d71c72012-05-03 01:28:5530#include "remoting/proto/control.pb.h"
[email protected]c78669c92011-06-13 22:42:3831#include "remoting/proto/event.pb.h"
[email protected]ff3761a12012-05-22 22:29:2432#include "remoting/protocol/client_stub.h"
[email protected]7f44ba42012-05-31 20:26:2933#include "remoting/protocol/clipboard_thread_proxy.h"
[email protected]88356922013-06-04 06:26:0134#include "remoting/protocol/pairing_registry.h"
sergeyub031cd22015-11-19 22:17:1335#include "remoting/protocol/session.h"
36#include "remoting/protocol/session_config.h"
[email protected]4e719f42014-08-12 18:04:3737#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
sergeyu1afb35a12015-02-13 18:45:3038#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
[email protected]c78669c92011-06-13 22:42:3839
[email protected]48a8ca32013-02-13 04:31:0140// Default DPI to assume for old clients that use notifyClientDimensions.
41const int kDefaultDPI = 96;
[email protected]739e2802013-03-18 01:03:4842
43namespace remoting {
[email protected]48a8ca32013-02-13 04:31:0144
sergeyu7bc87602015-02-13 20:33:2845namespace {
46
wez6e95a372015-07-08 22:33:3147// Name of command-line flag to disable use of I444 by default.
48const char kDisableI444SwitchName[] = "disable-i444";
wez43ac2662015-06-10 18:22:2949
sergeyu7bc87602015-02-13 20:33:2850scoped_ptr<VideoEncoder> CreateVideoEncoder(
51 const protocol::SessionConfig& config) {
52 const protocol::ChannelConfig& video_config = config.video_config();
53
54 if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) {
55 return VideoEncoderVpx::CreateForVP8().Pass();
56 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP9) {
57 return VideoEncoderVpx::CreateForVP9().Pass();
58 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
59 return make_scoped_ptr(new VideoEncoderVerbatim());
60 }
61
62 NOTREACHED();
63 return nullptr;
64}
65
66scoped_ptr<AudioEncoder> CreateAudioEncoder(
67 const protocol::SessionConfig& config) {
68 const protocol::ChannelConfig& audio_config = config.audio_config();
69
70 if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
71 return make_scoped_ptr(new AudioEncoderVerbatim());
72 } else if (audio_config.codec == protocol::ChannelConfig::CODEC_OPUS) {
73 return make_scoped_ptr(new AudioEncoderOpus());
74 }
75
76 NOTREACHED();
77 return nullptr;
78}
79
80} // namespace
81
[email protected]44f60762011-03-23 12:13:3582ClientSession::ClientSession(
83 EventHandler* event_handler,
[email protected]032d9dd2012-11-01 17:55:0484 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
[email protected]ce404ca2013-01-16 17:23:5385 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
[email protected]16dbfb0e2012-11-14 04:11:1986 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
87 scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
[email protected]170cba42012-09-12 22:28:3988 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
[email protected]ce404ca2013-01-16 17:23:5389 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
[email protected]3361e1f2012-03-20 20:31:4490 scoped_ptr<protocol::ConnectionToClient> connection,
[email protected]81904792012-10-18 04:16:2891 DesktopEnvironmentFactory* desktop_environment_factory,
[email protected]88356922013-06-04 06:26:0192 const base::TimeDelta& max_duration,
[email protected]1b478ba2014-07-31 12:51:4393 scoped_refptr<protocol::PairingRegistry> pairing_registry,
94 const std::vector<HostExtension*>& extensions)
[email protected]44f60762011-03-23 12:13:3595 : event_handler_(event_handler),
[email protected]3361e1f2012-03-20 20:31:4496 connection_(connection.Pass()),
97 client_jid_(connection_->session()->jid()),
[email protected]233bb942013-03-15 07:18:1798 desktop_environment_factory_(desktop_environment_factory),
[email protected]eccc2d42013-01-10 19:35:1499 input_tracker_(&host_input_filter_),
[email protected]86cbe6b2012-04-03 00:56:18100 remote_input_filter_(&input_tracker_),
[email protected]58f1ad42013-01-10 23:49:51101 mouse_clamping_filter_(&remote_input_filter_),
[email protected]eccc2d42013-01-10 19:35:14102 disable_input_filter_(mouse_clamping_filter_.input_filter()),
[email protected]750ae6b2012-08-20 22:52:40103 disable_clipboard_filter_(clipboard_echo_filter_.host_filter()),
[email protected]7f44ba42012-05-31 20:26:29104 client_clipboard_factory_(clipboard_echo_filter_.client_filter()),
[email protected]170cba42012-09-12 22:28:39105 max_duration_(max_duration),
[email protected]032d9dd2012-11-01 17:55:04106 audio_task_runner_(audio_task_runner),
[email protected]ce404ca2013-01-16 17:23:53107 input_task_runner_(input_task_runner),
[email protected]16dbfb0e2012-11-14 04:11:19108 video_capture_task_runner_(video_capture_task_runner),
109 video_encode_task_runner_(video_encode_task_runner),
[email protected]170cba42012-09-12 22:28:39110 network_task_runner_(network_task_runner),
[email protected]88356922013-06-04 06:26:01111 ui_task_runner_(ui_task_runner),
[email protected]1b478ba2014-07-31 12:51:43112 pairing_registry_(pairing_registry),
sergeyu1f8cd502015-02-13 21:45:53113 is_authenticated_(false),
[email protected]1b478ba2014-07-31 12:51:43114 pause_video_(false),
115 lossless_video_encode_(false),
wez6e95a372015-07-08 22:33:31116 // Note that |lossless_video_color_| defaults to true, but actually only
117 // controls VP9 video stream color quality.
118 lossless_video_color_(!base::CommandLine::ForCurrentProcess()->HasSwitch(
119 kDisableI444SwitchName)),
kulkarni.a933aeaf2014-09-20 13:19:17120 weak_factory_(this) {
[email protected]ee910fd2011-11-10 18:23:31121 connection_->SetEventHandler(this);
122
[email protected]1b478ba2014-07-31 12:51:43123 // Create a manager for the configured extensions, if any.
124 extension_manager_.reset(new HostExtensionSessionManager(extensions, this));
125
[email protected]2f4084892013-02-25 20:30:20126#if defined(OS_WIN)
127 // LocalInputMonitorWin filters out an echo of the injected input before it
128 // reaches |remote_input_filter_|.
129 remote_input_filter_.SetExpectLocalEcho(false);
130#endif // defined(OS_WIN)
[email protected]44f60762011-03-23 12:13:35131}
132
[email protected]f19f09ca2013-03-13 11:10:29133ClientSession::~ClientSession() {
134 DCHECK(CalledOnValidThread());
sergeyu7bc87602015-02-13 20:33:28135 DCHECK(!audio_pump_);
[email protected]231316a2013-03-25 06:01:12136 DCHECK(!desktop_environment_);
[email protected]b0b72f112013-03-24 03:42:42137 DCHECK(!input_injector_);
[email protected]231316a2013-03-25 06:01:12138 DCHECK(!screen_controls_);
sergeyu7bc87602015-02-13 20:33:28139 DCHECK(!video_frame_pump_);
[email protected]f19f09ca2013-03-13 11:10:29140
141 connection_.reset();
142}
143
[email protected]48a8ca32013-02-13 04:31:01144void ClientSession::NotifyClientResolution(
145 const protocol::ClientResolution& resolution) {
[email protected]a5d181f2013-04-19 14:55:37146 DCHECK(CalledOnValidThread());
147
[email protected]b9ed58f2013-05-16 10:45:24148 // TODO(sergeyu): Move these checks to protocol layer.
149 if (!resolution.has_dips_width() || !resolution.has_dips_height() ||
150 resolution.dips_width() < 0 || resolution.dips_height() < 0 ||
151 resolution.width() <= 0 || resolution.height() <= 0) {
152 LOG(ERROR) << "Received invalid ClientResolution message.";
[email protected]739e2802013-03-18 01:03:48153 return;
[email protected]b9ed58f2013-05-16 10:45:24154 }
[email protected]739e2802013-03-18 01:03:48155
156 VLOG(1) << "Received ClientResolution (dips_width="
157 << resolution.dips_width() << ", dips_height="
158 << resolution.dips_height() << ")";
159
[email protected]231316a2013-03-25 06:01:12160 if (!screen_controls_)
[email protected]739e2802013-03-18 01:03:48161 return;
162
163 ScreenResolution client_resolution(
[email protected]b9ed58f2013-05-16 10:45:24164 webrtc::DesktopSize(resolution.dips_width(), resolution.dips_height()),
165 webrtc::DesktopVector(kDefaultDPI, kDefaultDPI));
[email protected]739e2802013-03-18 01:03:48166
167 // Try to match the client's resolution.
[email protected]b9ed58f2013-05-16 10:45:24168 screen_controls_->SetScreenResolution(client_resolution);
[email protected]50d71c72012-05-03 01:28:55169}
170
171void ClientSession::ControlVideo(const protocol::VideoControl& video_control) {
[email protected]a5d181f2013-04-19 14:55:37172 DCHECK(CalledOnValidThread());
173
sergeyu10ce97b2015-02-05 23:53:14174 // Note that |video_frame_pump_| may be null, depending upon whether
175 // extensions choose to wrap or "steal" the video capturer or encoder.
[email protected]50d71c72012-05-03 01:28:55176 if (video_control.has_enable()) {
177 VLOG(1) << "Received VideoControl (enable="
178 << video_control.enable() << ")";
[email protected]1b478ba2014-07-31 12:51:43179 pause_video_ = !video_control.enable();
sergeyu1afb35a12015-02-13 18:45:30180 if (video_frame_pump_)
sergeyu10ce97b2015-02-05 23:53:14181 video_frame_pump_->Pause(pause_video_);
[email protected]50d71c72012-05-03 01:28:55182 }
[email protected]a516f1e2014-05-30 07:21:20183 if (video_control.has_lossless_encode()) {
184 VLOG(1) << "Received VideoControl (lossless_encode="
185 << video_control.lossless_encode() << ")";
[email protected]1b478ba2014-07-31 12:51:43186 lossless_video_encode_ = video_control.lossless_encode();
sergeyu1afb35a12015-02-13 18:45:30187 if (video_frame_pump_)
sergeyu10ce97b2015-02-05 23:53:14188 video_frame_pump_->SetLosslessEncode(lossless_video_encode_);
[email protected]a516f1e2014-05-30 07:21:20189 }
190 if (video_control.has_lossless_color()) {
191 VLOG(1) << "Received VideoControl (lossless_color="
192 << video_control.lossless_color() << ")";
[email protected]1b478ba2014-07-31 12:51:43193 lossless_video_color_ = video_control.lossless_color();
sergeyu1afb35a12015-02-13 18:45:30194 if (video_frame_pump_)
sergeyu10ce97b2015-02-05 23:53:14195 video_frame_pump_->SetLosslessColor(lossless_video_color_);
[email protected]a516f1e2014-05-30 07:21:20196 }
[email protected]f2b9cf32012-04-27 00:13:43197}
198
[email protected]f458bed2012-10-18 03:27:59199void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) {
[email protected]a5d181f2013-04-19 14:55:37200 DCHECK(CalledOnValidThread());
201
[email protected]f458bed2012-10-18 03:27:59202 if (audio_control.has_enable()) {
203 VLOG(1) << "Received AudioControl (enable="
204 << audio_control.enable() << ")";
sergeyu7bc87602015-02-13 20:33:28205 if (audio_pump_)
206 audio_pump_->Pause(!audio_control.enable());
[email protected]f458bed2012-10-18 03:27:59207 }
208}
209
[email protected]a5d181f2013-04-19 14:55:37210void ClientSession::SetCapabilities(
211 const protocol::Capabilities& capabilities) {
212 DCHECK(CalledOnValidThread());
213
[email protected]a5d181f2013-04-19 14:55:37214 // Ignore all the messages but the 1st one.
215 if (client_capabilities_) {
216 LOG(WARNING) << "protocol::Capabilities has been received already.";
217 return;
218 }
219
[email protected]1b478ba2014-07-31 12:51:43220 // Compute the set of capabilities supported by both client and host.
[email protected]a5d181f2013-04-19 14:55:37221 client_capabilities_ = make_scoped_ptr(new std::string());
222 if (capabilities.has_capabilities())
223 *client_capabilities_ = capabilities.capabilities();
[email protected]1b478ba2014-07-31 12:51:43224 capabilities_ = IntersectCapabilities(*client_capabilities_,
225 host_capabilities_);
226 extension_manager_->OnNegotiatedCapabilities(
227 connection_->client_stub(), capabilities_);
[email protected]a5d181f2013-04-19 14:55:37228
229 VLOG(1) << "Client capabilities: " << *client_capabilities_;
230
231 // Calculate the set of capabilities enabled by both client and host and
232 // pass it to the desktop environment if it is available.
[email protected]1b478ba2014-07-31 12:51:43233 desktop_environment_->SetCapabilities(capabilities_);
[email protected]a5d181f2013-04-19 14:55:37234}
235
[email protected]88356922013-06-04 06:26:01236void ClientSession::RequestPairing(
237 const protocol::PairingRequest& pairing_request) {
dchengac10e4a82014-08-26 03:53:44238 if (pairing_registry_.get() && pairing_request.has_client_name()) {
[email protected]88356922013-06-04 06:26:01239 protocol::PairingRegistry::Pairing pairing =
240 pairing_registry_->CreatePairing(pairing_request.client_name());
241 protocol::PairingResponse pairing_response;
[email protected]df5189f2013-06-18 12:12:05242 pairing_response.set_client_id(pairing.client_id());
243 pairing_response.set_shared_secret(pairing.shared_secret());
[email protected]88356922013-06-04 06:26:01244 connection_->client_stub()->SetPairingResponse(pairing_response);
245 }
246}
247
[email protected]09eabd65c2013-08-13 00:13:48248void ClientSession::DeliverClientMessage(
249 const protocol::ExtensionMessage& message) {
[email protected]af278c42013-09-02 05:27:00250 if (message.has_type()) {
251 if (message.type() == "test-echo") {
252 protocol::ExtensionMessage reply;
253 reply.set_type("test-echo-reply");
254 if (message.has_data())
255 reply.set_data(message.data().substr(0, 16));
256 connection_->client_stub()->DeliverHostMessage(reply);
257 return;
[email protected]3a5b82c2014-02-20 13:28:14258 } else if (message.type() == "gnubby-auth") {
259 if (gnubby_auth_handler_) {
260 gnubby_auth_handler_->DeliverClientMessage(message.data());
261 } else {
262 HOST_LOG << "gnubby auth is not enabled";
263 }
264 return;
[email protected]399b4f62014-05-30 20:13:15265 } else {
wez73f19de2014-10-29 19:06:33266 if (extension_manager_->OnExtensionMessage(message))
wez87036992014-09-05 00:53:43267 return;
268
269 DLOG(INFO) << "Unexpected message received: "
270 << message.type() << ": " << message.data();
[email protected]af278c42013-09-02 05:27:00271 }
272 }
[email protected]09eabd65c2013-08-13 00:13:48273}
274
[email protected]064128c2014-04-07 22:33:28275void ClientSession::OnConnectionAuthenticating(
276 protocol::ConnectionToClient* connection) {
277 event_handler_->OnSessionAuthenticating(this);
278}
279
[email protected]cba6f812012-03-27 01:01:50280void ClientSession::OnConnectionAuthenticated(
[email protected]ee910fd2011-11-10 18:23:31281 protocol::ConnectionToClient* connection) {
[email protected]86cbe6b2012-04-03 00:56:18282 DCHECK(CalledOnValidThread());
283 DCHECK_EQ(connection_.get(), connection);
sergeyu7bc87602015-02-13 20:33:28284 DCHECK(!audio_pump_);
[email protected]a5d181f2013-04-19 14:55:37285 DCHECK(!desktop_environment_);
[email protected]324b1962013-05-01 19:30:22286 DCHECK(!input_injector_);
287 DCHECK(!screen_controls_);
sergeyu7bc87602015-02-13 20:33:28288 DCHECK(!video_frame_pump_);
[email protected]34df2ab2012-08-19 06:54:23289
sergeyu1f8cd502015-02-13 21:45:53290 is_authenticated_ = true;
[email protected]34df2ab2012-08-19 06:54:23291
[email protected]5dc5b12a2012-06-23 01:05:14292 if (max_duration_ > base::TimeDelta()) {
sergeyuec77d8542015-11-03 22:31:00293 max_duration_timer_.Start(
294 FROM_HERE, max_duration_,
295 base::Bind(&ClientSession::DisconnectSession, base::Unretained(this),
296 protocol::MAX_SESSION_LENGTH));
[email protected]5dc5b12a2012-06-23 01:05:14297 }
[email protected]34df2ab2012-08-19 06:54:23298
[email protected]324b1962013-05-01 19:30:22299 // Disconnect the session if the connection was rejected by the host.
300 if (!event_handler_->OnSessionAuthenticated(this)) {
sergeyuec77d8542015-11-03 22:31:00301 DisconnectSession(protocol::SESSION_REJECTED);
[email protected]324b1962013-05-01 19:30:22302 return;
303 }
[email protected]ce404ca2013-01-16 17:23:53304
[email protected]96361d02013-05-08 18:26:18305 // Create the desktop environment. Drop the connection if it could not be
306 // created for any reason (for instance the curtain could not initialize).
[email protected]231316a2013-03-25 06:01:12307 desktop_environment_ =
kulkarni.a933aeaf2014-09-20 13:19:17308 desktop_environment_factory_->Create(weak_factory_.GetWeakPtr());
[email protected]96361d02013-05-08 18:26:18309 if (!desktop_environment_) {
sergeyuec77d8542015-11-03 22:31:00310 DisconnectSession(protocol::HOST_CONFIGURATION_ERROR);
[email protected]96361d02013-05-08 18:26:18311 return;
312 }
313
sergeyu1f8cd502015-02-13 21:45:53314 // Connect host stub.
315 connection_->set_host_stub(this);
316
317 // Connect video stub.
318 mouse_clamping_filter_.set_video_stub(connection_->video_stub());
319
[email protected]1b478ba2014-07-31 12:51:43320 // Collate the set of capabilities to offer the client, if it supports them.
sergeyuf69b019f2014-09-13 20:41:02321 host_capabilities_ = desktop_environment_->GetCapabilities();
322 if (!host_capabilities_.empty())
323 host_capabilities_.append(" ");
324 host_capabilities_.append(extension_manager_->GetCapabilities());
[email protected]233bb942013-03-15 07:18:17325
[email protected]231316a2013-03-25 06:01:12326 // Create the object that controls the screen resolution.
327 screen_controls_ = desktop_environment_->CreateScreenControls();
[email protected]61cfdc52013-03-09 03:04:56328
[email protected]324b1962013-05-01 19:30:22329 // Create the event executor.
[email protected]231316a2013-03-25 06:01:12330 input_injector_ = desktop_environment_->CreateInputInjector();
[email protected]eccc2d42013-01-10 19:35:14331
sergeyu1f8cd502015-02-13 21:45:53332 // Connect the host input stubs.
333 connection_->set_input_stub(&disable_input_filter_);
[email protected]b0b72f112013-03-24 03:42:42334 host_input_filter_.set_input_stub(input_injector_.get());
sergeyu1f8cd502015-02-13 21:45:53335
336 // Connect the clipboard stubs.
337 connection_->set_clipboard_stub(&disable_clipboard_filter_);
[email protected]b0b72f112013-03-24 03:42:42338 clipboard_echo_filter_.set_host_stub(input_injector_.get());
sergeyu1f8cd502015-02-13 21:45:53339 clipboard_echo_filter_.set_client_stub(connection_->client_stub());
[email protected]eccc2d42013-01-10 19:35:14340
[email protected]3a5b82c2014-02-20 13:28:14341 // Create a GnubbyAuthHandler to proxy gnubbyd messages.
342 gnubby_auth_handler_ = desktop_environment_->CreateGnubbyAuthHandler(
343 connection_->client_stub());
[email protected]324b1962013-05-01 19:30:22344}
345
346void ClientSession::OnConnectionChannelsConnected(
347 protocol::ConnectionToClient* connection) {
348 DCHECK(CalledOnValidThread());
349 DCHECK_EQ(connection_.get(), connection);
350
351 // Negotiate capabilities with the client.
sergeyuf69b019f2014-09-13 20:41:02352 VLOG(1) << "Host capabilities: " << host_capabilities_;
sergeyuf69b019f2014-09-13 20:41:02353 protocol::Capabilities capabilities;
354 capabilities.set_capabilities(host_capabilities_);
355 connection_->client_stub()->SetCapabilities(capabilities);
[email protected]324b1962013-05-01 19:30:22356
357 // Start the event executor.
358 input_injector_->Start(CreateClipboardProxy());
359 SetDisableInputs(false);
360
[email protected]1b478ba2014-07-31 12:51:43361 // Start recording video.
362 ResetVideoPipeline();
[email protected]324b1962013-05-01 19:30:22363
sergeyu7bc87602015-02-13 20:33:28364 // Create an AudioPump if audio is enabled, to pump audio samples.
365 if (connection_->session()->config().is_audio_enabled()) {
366 scoped_ptr<AudioEncoder> audio_encoder =
367 CreateAudioEncoder(connection_->session()->config());
368 audio_pump_.reset(new AudioPump(
369 audio_task_runner_, desktop_environment_->CreateAudioCapturer(),
370 audio_encoder.Pass(), connection_->audio_stub()));
371 }
[email protected]170cba42012-09-12 22:28:39372
[email protected]cdd1c9e2012-10-26 21:14:04373 // Notify the event handler that all our channels are now connected.
[email protected]cba6f812012-03-27 01:01:50374 event_handler_->OnSessionChannelsConnected(this);
[email protected]ee910fd2011-11-10 18:23:31375}
376
[email protected]cba6f812012-03-27 01:01:50377void ClientSession::OnConnectionClosed(
[email protected]1f249e22011-11-29 20:19:59378 protocol::ConnectionToClient* connection,
[email protected]204a9e32012-03-02 05:42:58379 protocol::ErrorCode error) {
[email protected]ec6411872011-11-11 03:28:55380 DCHECK(CalledOnValidThread());
[email protected]ee910fd2011-11-10 18:23:31381 DCHECK_EQ(connection_.get(), connection);
[email protected]750ae6b2012-08-20 22:52:40382
lukaszaf34d8412015-04-30 23:09:59383 HOST_LOG << "Client disconnected: " << client_jid_ << "; error = " << error;
384
[email protected]231316a2013-03-25 06:01:12385 // Ignore any further callbacks.
kulkarni.a933aeaf2014-09-20 13:19:17386 weak_factory_.InvalidateWeakPtrs();
[email protected]a031c972012-12-27 20:10:40387
[email protected]24a2a9d22012-12-07 09:06:47388 // If the client never authenticated then the session failed.
sergeyu1f8cd502015-02-13 21:45:53389 if (!is_authenticated_)
[email protected]1f249e22011-11-29 20:19:59390 event_handler_->OnSessionAuthenticationFailed(this);
[email protected]750ae6b2012-08-20 22:52:40391
[email protected]86cbe6b2012-04-03 00:56:18392 // Ensure that any pressed keys or buttons are released.
393 input_tracker_.ReleaseAll();
394
[email protected]24a2a9d22012-12-07 09:06:47395 // Stop components access the client, audio or video stubs, which are no
396 // longer valid once ConnectionToClient calls OnConnectionClosed().
sergeyu7bc87602015-02-13 20:33:28397 audio_pump_.reset();
sergeyu1afb35a12015-02-13 18:45:30398 video_frame_pump_.reset();
399 mouse_shape_pump_.reset();
[email protected]24a2a9d22012-12-07 09:06:47400 client_clipboard_factory_.InvalidateWeakPtrs();
[email protected]b0b72f112013-03-24 03:42:42401 input_injector_.reset();
[email protected]231316a2013-03-25 06:01:12402 screen_controls_.reset();
403 desktop_environment_.reset();
[email protected]24a2a9d22012-12-07 09:06:47404
405 // Notify the ChromotingHost that this client is disconnected.
[email protected]ee910fd2011-11-10 18:23:31406 event_handler_->OnSessionClosed(this);
[email protected]ee910fd2011-11-10 18:23:31407}
408
sergeyu752c6e62015-09-30 06:40:27409void ClientSession::OnInputEventReceived(
410 protocol::ConnectionToClient* connection,
411 int64_t event_timestamp) {
[email protected]ec6411872011-11-11 03:28:55412 DCHECK(CalledOnValidThread());
[email protected]ee910fd2011-11-10 18:23:31413 DCHECK_EQ(connection_.get(), connection);
[email protected]170cba42012-09-12 22:28:39414
sergeyu10ce97b2015-02-05 23:53:14415 if (video_frame_pump_.get())
sergeyu752c6e62015-09-30 06:40:27416 video_frame_pump_->OnInputEventReceived(event_timestamp);
[email protected]ee910fd2011-11-10 18:23:31417}
418
[email protected]17af2ab2012-02-02 04:07:52419void ClientSession::OnRouteChange(
420 protocol::ConnectionToClient* connection,
421 const std::string& channel_name,
[email protected]be451c82012-03-20 22:24:47422 const protocol::TransportRoute& route) {
[email protected]91e4b7f62012-01-25 23:23:02423 DCHECK(CalledOnValidThread());
424 DCHECK_EQ(connection_.get(), connection);
[email protected]be451c82012-03-20 22:24:47425 event_handler_->OnSessionRouteChange(this, channel_name, route);
[email protected]91e4b7f62012-01-25 23:23:02426}
427
[email protected]231316a2013-03-25 06:01:12428const std::string& ClientSession::client_jid() const {
429 return client_jid_;
430}
431
sergeyuec77d8542015-11-03 22:31:00432void ClientSession::DisconnectSession(protocol::ErrorCode error) {
[email protected]ec6411872011-11-11 03:28:55433 DCHECK(CalledOnValidThread());
434 DCHECK(connection_.get());
[email protected]a46bcef2011-11-11 01:27:23435
[email protected]5dc5b12a2012-06-23 01:05:14436 max_duration_timer_.Stop();
[email protected]24a2a9d22012-12-07 09:06:47437
[email protected]86cbe6b2012-04-03 00:56:18438 // This triggers OnConnectionClosed(), and the session may be destroyed
[email protected]a46bcef2011-11-11 01:27:23439 // as the result, so this call must be the last in this method.
sergeyuec77d8542015-11-03 22:31:00440 connection_->Disconnect(error);
[email protected]44f60762011-03-23 12:13:35441}
442
[email protected]8c83a71c2013-12-16 18:02:58443void ClientSession::OnLocalMouseMoved(const webrtc::DesktopVector& position) {
[email protected]ec6411872011-11-11 03:28:55444 DCHECK(CalledOnValidThread());
[email protected]231316a2013-03-25 06:01:12445 remote_input_filter_.LocalMouseMoved(position);
[email protected]86cbe6b2012-04-03 00:56:18446}
[email protected]ec6411872011-11-11 03:28:55447
[email protected]86cbe6b2012-04-03 00:56:18448void ClientSession::SetDisableInputs(bool disable_inputs) {
449 DCHECK(CalledOnValidThread());
450
[email protected]750ae6b2012-08-20 22:52:40451 if (disable_inputs)
[email protected]86cbe6b2012-04-03 00:56:18452 input_tracker_.ReleaseAll();
[email protected]750ae6b2012-08-20 22:52:40453
454 disable_input_filter_.set_enabled(!disable_inputs);
455 disable_clipboard_filter_.set_enabled(!disable_inputs);
[email protected]c78669c92011-06-13 22:42:38456}
457
[email protected]1b478ba2014-07-31 12:51:43458void ClientSession::ResetVideoPipeline() {
459 DCHECK(CalledOnValidThread());
460
sergeyu1afb35a12015-02-13 18:45:30461 mouse_shape_pump_.reset();
sergeyu97568a8162015-02-24 18:00:55462 connection_->set_video_feedback_stub(nullptr);
sergeyu1afb35a12015-02-13 18:45:30463 video_frame_pump_.reset();
[email protected]1b478ba2014-07-31 12:51:43464
[email protected]4e719f42014-08-12 18:04:37465 // Create VideoEncoder and DesktopCapturer to match the session's video
466 // channel configuration.
467 scoped_ptr<webrtc::DesktopCapturer> video_capturer =
wezea125162014-08-29 01:41:52468 desktop_environment_->CreateVideoCapturer();
469 extension_manager_->OnCreateVideoCapturer(&video_capturer);
[email protected]1b478ba2014-07-31 12:51:43470 scoped_ptr<VideoEncoder> video_encoder =
wezea125162014-08-29 01:41:52471 CreateVideoEncoder(connection_->session()->config());
472 extension_manager_->OnCreateVideoEncoder(&video_encoder);
[email protected]1b478ba2014-07-31 12:51:43473
sergeyu10ce97b2015-02-05 23:53:14474 // Don't start the VideoFramePump if either capturer or encoder are missing.
[email protected]1b478ba2014-07-31 12:51:43475 if (!video_capturer || !video_encoder)
476 return;
477
sergeyu1afb35a12015-02-13 18:45:30478 // Create MouseShapePump to send mouse cursor shape.
479 mouse_shape_pump_.reset(
480 new MouseShapePump(video_capture_task_runner_,
481 desktop_environment_->CreateMouseCursorMonitor(),
482 connection_->client_stub()));
483
484 // Create a VideoFramePump to pump frames from the capturer to the client.'
485 //
486 // TODO(sergeyu): Move DesktopCapturerProxy creation to DesktopEnvironment.
487 // When using IpcDesktopCapturer the capture thread is not useful.
488 scoped_ptr<DesktopCapturerProxy> capturer_proxy(new DesktopCapturerProxy(
489 video_capture_task_runner_, video_capturer.Pass()));
490 video_frame_pump_.reset(
491 new VideoFramePump(video_encode_task_runner_, capturer_proxy.Pass(),
492 video_encoder.Pass(), &mouse_clamping_filter_));
[email protected]1b478ba2014-07-31 12:51:43493
494 // Apply video-control parameters to the new scheduler.
sergeyu10ce97b2015-02-05 23:53:14495 video_frame_pump_->SetLosslessEncode(lossless_video_encode_);
496 video_frame_pump_->SetLosslessColor(lossless_video_color_);
[email protected]1b478ba2014-07-31 12:51:43497
sergeyu91f93b62015-02-05 20:14:30498 // Pause capturing if necessary.
sergeyu10ce97b2015-02-05 23:53:14499 video_frame_pump_->Pause(pause_video_);
sergeyu97568a8162015-02-24 18:00:55500
501 connection_->set_video_feedback_stub(
502 video_frame_pump_->video_feedback_stub());
[email protected]1b478ba2014-07-31 12:51:43503}
504
[email protected]3a5b82c2014-02-20 13:28:14505void ClientSession::SetGnubbyAuthHandlerForTesting(
506 GnubbyAuthHandler* gnubby_auth_handler) {
[email protected]1b478ba2014-07-31 12:51:43507 DCHECK(CalledOnValidThread());
[email protected]3a5b82c2014-02-20 13:28:14508 gnubby_auth_handler_.reset(gnubby_auth_handler);
509}
510
[email protected]7f44ba42012-05-31 20:26:29511scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() {
512 DCHECK(CalledOnValidThread());
513
sergeyu2d690882014-10-01 02:36:43514 return make_scoped_ptr(
515 new protocol::ClipboardThreadProxy(client_clipboard_factory_.GetWeakPtr(),
anujk.sharmabb802932015-05-05 21:57:29516 base::ThreadTaskRunnerHandle::Get()));
[email protected]7f44ba42012-05-31 20:26:29517}
518
[email protected]44f60762011-03-23 12:13:35519} // namespace remoting