blob: da82ef7d64f784f72dfc08a62230adbd05c9832c [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>
sergeyu1417e0132015-12-23 19:01:228#include <utility>
[email protected]4fe827a2011-08-10 03:30:199
wez43ac2662015-06-10 18:22:2910#include "base/command_line.h"
dcheng0765c492016-04-06 22:41:5311#include "base/memory/ptr_util.h"
anujk.sharmabb802932015-05-05 21:57:2912#include "base/single_thread_task_runner.h"
gabbac02f52016-05-11 17:55:5113#include "base/threading/thread_task_runner_handle.h"
avic5960f32015-12-22 22:49:4814#include "build/build_config.h"
[email protected]a5d181f2013-04-19 14:55:3715#include "remoting/base/capabilities.h"
sergeyu00a67b12016-04-01 00:07:0016#include "remoting/base/constants.h"
[email protected]6f742dd02013-11-26 23:19:5017#include "remoting/base/logging.h"
[email protected]ce404ca2013-01-16 17:23:5318#include "remoting/host/audio_capturer.h"
[email protected]170cba42012-09-12 22:28:3919#include "remoting/host/desktop_environment.h"
[email protected]399b4f62014-05-30 20:13:1520#include "remoting/host/host_extension_session.h"
[email protected]b0b72f112013-03-24 03:42:4221#include "remoting/host/input_injector.h"
sergeyu1afb35a12015-02-13 18:45:3022#include "remoting/host/mouse_shape_pump.h"
[email protected]231316a2013-03-25 06:01:1223#include "remoting/host/screen_controls.h"
[email protected]739e2802013-03-18 01:03:4824#include "remoting/host/screen_resolution.h"
[email protected]50d71c72012-05-03 01:28:5525#include "remoting/proto/control.pb.h"
[email protected]c78669c92011-06-13 22:42:3826#include "remoting/proto/event.pb.h"
sergeyucd16e2062016-09-12 19:28:3527#include "remoting/protocol/audio_stream.h"
[email protected]ff3761a12012-05-22 22:29:2428#include "remoting/protocol/client_stub.h"
[email protected]7f44ba42012-05-31 20:26:2929#include "remoting/protocol/clipboard_thread_proxy.h"
[email protected]88356922013-06-04 06:26:0130#include "remoting/protocol/pairing_registry.h"
sergeyub031cd22015-11-19 22:17:1331#include "remoting/protocol/session.h"
32#include "remoting/protocol/session_config.h"
sergeyu4d208002015-11-23 22:27:4333#include "remoting/protocol/video_frame_pump.h"
[email protected]4e719f42014-08-12 18:04:3734#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
[email protected]c78669c92011-06-13 22:42:3835
[email protected]739e2802013-03-18 01:03:4836namespace remoting {
[email protected]48a8ca32013-02-13 04:31:0137
sergeyu7bc87602015-02-13 20:33:2838namespace {
39
wez6e95a372015-07-08 22:33:3140// Name of command-line flag to disable use of I444 by default.
41const char kDisableI444SwitchName[] = "disable-i444";
wez43ac2662015-06-10 18:22:2942
sergeyu7bc87602015-02-13 20:33:2843} // namespace
44
[email protected]44f60762011-03-23 12:13:3545ClientSession::ClientSession(
46 EventHandler* event_handler,
dcheng0765c492016-04-06 22:41:5347 std::unique_ptr<protocol::ConnectionToClient> connection,
[email protected]81904792012-10-18 04:16:2848 DesktopEnvironmentFactory* desktop_environment_factory,
zijiehe4aa6ea42016-11-12 01:28:1649 const DesktopEnvironmentOptions& desktop_environment_options,
[email protected]88356922013-06-04 06:26:0150 const base::TimeDelta& max_duration,
[email protected]1b478ba2014-07-31 12:51:4351 scoped_refptr<protocol::PairingRegistry> pairing_registry,
52 const std::vector<HostExtension*>& extensions)
[email protected]44f60762011-03-23 12:13:3553 : event_handler_(event_handler),
sergeyu1417e0132015-12-23 19:01:2254 connection_(std::move(connection)),
[email protected]3361e1f2012-03-20 20:31:4455 client_jid_(connection_->session()->jid()),
[email protected]233bb942013-03-15 07:18:1756 desktop_environment_factory_(desktop_environment_factory),
zijiehe4aa6ea42016-11-12 01:28:1657 desktop_environment_options_(desktop_environment_options),
[email protected]eccc2d42013-01-10 19:35:1458 input_tracker_(&host_input_filter_),
[email protected]86cbe6b2012-04-03 00:56:1859 remote_input_filter_(&input_tracker_),
[email protected]58f1ad42013-01-10 23:49:5160 mouse_clamping_filter_(&remote_input_filter_),
sergeyua609b7a2015-11-30 06:25:3961 disable_input_filter_(&mouse_clamping_filter_),
[email protected]750ae6b2012-08-20 22:52:4062 disable_clipboard_filter_(clipboard_echo_filter_.host_filter()),
[email protected]7f44ba42012-05-31 20:26:2963 client_clipboard_factory_(clipboard_echo_filter_.client_filter()),
[email protected]170cba42012-09-12 22:28:3964 max_duration_(max_duration),
[email protected]1b478ba2014-07-31 12:51:4365 pairing_registry_(pairing_registry),
wez6e95a372015-07-08 22:33:3166 // Note that |lossless_video_color_| defaults to true, but actually only
67 // controls VP9 video stream color quality.
68 lossless_video_color_(!base::CommandLine::ForCurrentProcess()->HasSwitch(
69 kDisableI444SwitchName)),
kulkarni.a933aeaf2014-09-20 13:19:1770 weak_factory_(this) {
zijiehef38c9722017-02-08 02:05:2971 connection_->session()->AddPlugin(&host_experiment_session_plugin_);
[email protected]ee910fd2011-11-10 18:23:3172 connection_->SetEventHandler(this);
73
[email protected]1b478ba2014-07-31 12:51:4374 // Create a manager for the configured extensions, if any.
75 extension_manager_.reset(new HostExtensionSessionManager(extensions, this));
76
[email protected]2f4084892013-02-25 20:30:2077#if defined(OS_WIN)
78 // LocalInputMonitorWin filters out an echo of the injected input before it
79 // reaches |remote_input_filter_|.
80 remote_input_filter_.SetExpectLocalEcho(false);
81#endif // defined(OS_WIN)
[email protected]44f60762011-03-23 12:13:3582}
83
[email protected]f19f09ca2013-03-13 11:10:2984ClientSession::~ClientSession() {
gabbf77513a2017-06-01 14:35:3485 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
sergeyucd16e2062016-09-12 19:28:3586 DCHECK(!audio_stream_);
[email protected]231316a2013-03-25 06:01:1287 DCHECK(!desktop_environment_);
[email protected]b0b72f112013-03-24 03:42:4288 DCHECK(!input_injector_);
[email protected]231316a2013-03-25 06:01:1289 DCHECK(!screen_controls_);
sergeyua609b7a2015-11-30 06:25:3990 DCHECK(!video_stream_);
[email protected]f19f09ca2013-03-13 11:10:2991
92 connection_.reset();
93}
94
[email protected]48a8ca32013-02-13 04:31:0195void ClientSession::NotifyClientResolution(
96 const protocol::ClientResolution& resolution) {
gabbf77513a2017-06-01 14:35:3497 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
sergeyu54624e12016-06-01 10:54:3198 DCHECK(resolution.dips_width() > 0 && resolution.dips_height() > 0);
[email protected]739e2802013-03-18 01:03:4899
100 VLOG(1) << "Received ClientResolution (dips_width="
101 << resolution.dips_width() << ", dips_height="
102 << resolution.dips_height() << ")";
103
[email protected]231316a2013-03-25 06:01:12104 if (!screen_controls_)
[email protected]739e2802013-03-18 01:03:48105 return;
106
sergeyuf00bde32016-08-09 22:10:02107 webrtc::DesktopSize client_size(resolution.dips_width(),
108 resolution.dips_height());
109 if (connection_->session()->config().protocol() ==
110 protocol::SessionConfig::Protocol::WEBRTC) {
111 // When using WebRTC round down the dimensions to multiple of 2. Otherwise
112 // the dimensions will be rounded on the receiver, which will cause blurring
113 // due to scaling. The resulting size is still close to the client size and
114 // will fit on the client's screen without scaling.
115 // TODO(sergeyu): Make WebRTC handle odd dimensions properly.
116 // crbug.com/636071
117 client_size.set(client_size.width() & (~1), client_size.height() & (~1));
118 }
[email protected]739e2802013-03-18 01:03:48119
120 // Try to match the client's resolution.
sergeyuf00bde32016-08-09 22:10:02121 // TODO(sergeyu): Pass clients DPI to the resizer.
122 screen_controls_->SetScreenResolution(ScreenResolution(
123 client_size, webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)));
[email protected]50d71c72012-05-03 01:28:55124}
125
126void ClientSession::ControlVideo(const protocol::VideoControl& video_control) {
gabbf77513a2017-06-01 14:35:34127 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]a5d181f2013-04-19 14:55:37128
sergeyua609b7a2015-11-30 06:25:39129 // Note that |video_stream_| may be null, depending upon whether
sergeyu10ce97b2015-02-05 23:53:14130 // extensions choose to wrap or "steal" the video capturer or encoder.
[email protected]50d71c72012-05-03 01:28:55131 if (video_control.has_enable()) {
132 VLOG(1) << "Received VideoControl (enable="
133 << video_control.enable() << ")";
[email protected]1b478ba2014-07-31 12:51:43134 pause_video_ = !video_control.enable();
sergeyua609b7a2015-11-30 06:25:39135 if (video_stream_)
136 video_stream_->Pause(pause_video_);
[email protected]50d71c72012-05-03 01:28:55137 }
[email protected]a516f1e2014-05-30 07:21:20138 if (video_control.has_lossless_encode()) {
139 VLOG(1) << "Received VideoControl (lossless_encode="
140 << video_control.lossless_encode() << ")";
[email protected]1b478ba2014-07-31 12:51:43141 lossless_video_encode_ = video_control.lossless_encode();
sergeyua609b7a2015-11-30 06:25:39142 if (video_stream_)
143 video_stream_->SetLosslessEncode(lossless_video_encode_);
[email protected]a516f1e2014-05-30 07:21:20144 }
145 if (video_control.has_lossless_color()) {
146 VLOG(1) << "Received VideoControl (lossless_color="
147 << video_control.lossless_color() << ")";
[email protected]1b478ba2014-07-31 12:51:43148 lossless_video_color_ = video_control.lossless_color();
sergeyua609b7a2015-11-30 06:25:39149 if (video_stream_)
150 video_stream_->SetLosslessColor(lossless_video_color_);
[email protected]a516f1e2014-05-30 07:21:20151 }
[email protected]f2b9cf32012-04-27 00:13:43152}
153
[email protected]f458bed2012-10-18 03:27:59154void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) {
gabbf77513a2017-06-01 14:35:34155 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]a5d181f2013-04-19 14:55:37156
[email protected]f458bed2012-10-18 03:27:59157 if (audio_control.has_enable()) {
158 VLOG(1) << "Received AudioControl (enable="
159 << audio_control.enable() << ")";
sergeyucd16e2062016-09-12 19:28:35160 if (audio_stream_)
161 audio_stream_->Pause(!audio_control.enable());
[email protected]f458bed2012-10-18 03:27:59162 }
163}
164
[email protected]a5d181f2013-04-19 14:55:37165void ClientSession::SetCapabilities(
166 const protocol::Capabilities& capabilities) {
gabbf77513a2017-06-01 14:35:34167 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]a5d181f2013-04-19 14:55:37168
[email protected]a5d181f2013-04-19 14:55:37169 // Ignore all the messages but the 1st one.
170 if (client_capabilities_) {
171 LOG(WARNING) << "protocol::Capabilities has been received already.";
172 return;
173 }
174
[email protected]1b478ba2014-07-31 12:51:43175 // Compute the set of capabilities supported by both client and host.
ricea68860bd2016-08-22 02:48:56176 client_capabilities_ = base::MakeUnique<std::string>();
[email protected]a5d181f2013-04-19 14:55:37177 if (capabilities.has_capabilities())
178 *client_capabilities_ = capabilities.capabilities();
[email protected]1b478ba2014-07-31 12:51:43179 capabilities_ = IntersectCapabilities(*client_capabilities_,
180 host_capabilities_);
181 extension_manager_->OnNegotiatedCapabilities(
182 connection_->client_stub(), capabilities_);
[email protected]a5d181f2013-04-19 14:55:37183
184 VLOG(1) << "Client capabilities: " << *client_capabilities_;
185
[email protected]1b478ba2014-07-31 12:51:43186 desktop_environment_->SetCapabilities(capabilities_);
[email protected]a5d181f2013-04-19 14:55:37187}
188
[email protected]88356922013-06-04 06:26:01189void ClientSession::RequestPairing(
190 const protocol::PairingRequest& pairing_request) {
dchengac10e4a82014-08-26 03:53:44191 if (pairing_registry_.get() && pairing_request.has_client_name()) {
[email protected]88356922013-06-04 06:26:01192 protocol::PairingRegistry::Pairing pairing =
193 pairing_registry_->CreatePairing(pairing_request.client_name());
194 protocol::PairingResponse pairing_response;
[email protected]df5189f2013-06-18 12:12:05195 pairing_response.set_client_id(pairing.client_id());
196 pairing_response.set_shared_secret(pairing.shared_secret());
[email protected]88356922013-06-04 06:26:01197 connection_->client_stub()->SetPairingResponse(pairing_response);
198 }
199}
200
[email protected]09eabd65c2013-08-13 00:13:48201void ClientSession::DeliverClientMessage(
202 const protocol::ExtensionMessage& message) {
[email protected]af278c42013-09-02 05:27:00203 if (message.has_type()) {
204 if (message.type() == "test-echo") {
205 protocol::ExtensionMessage reply;
206 reply.set_type("test-echo-reply");
207 if (message.has_data())
208 reply.set_data(message.data().substr(0, 16));
209 connection_->client_stub()->DeliverHostMessage(reply);
210 return;
[email protected]399b4f62014-05-30 20:13:15211 } else {
wez73f19de2014-10-29 19:06:33212 if (extension_manager_->OnExtensionMessage(message))
wez87036992014-09-05 00:53:43213 return;
214
215 DLOG(INFO) << "Unexpected message received: "
216 << message.type() << ": " << message.data();
[email protected]af278c42013-09-02 05:27:00217 }
218 }
[email protected]09eabd65c2013-08-13 00:13:48219}
220
sergeyu4e1f4cd2016-09-27 00:42:52221void ClientSession::OnConnectionAuthenticating() {
[email protected]064128c2014-04-07 22:33:28222 event_handler_->OnSessionAuthenticating(this);
223}
224
sergeyu4e1f4cd2016-09-27 00:42:52225void ClientSession::OnConnectionAuthenticated() {
gabbf77513a2017-06-01 14:35:34226 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
sergeyucd16e2062016-09-12 19:28:35227 DCHECK(!audio_stream_);
[email protected]a5d181f2013-04-19 14:55:37228 DCHECK(!desktop_environment_);
[email protected]324b1962013-05-01 19:30:22229 DCHECK(!input_injector_);
230 DCHECK(!screen_controls_);
sergeyua609b7a2015-11-30 06:25:39231 DCHECK(!video_stream_);
[email protected]34df2ab2012-08-19 06:54:23232
sergeyu1f8cd502015-02-13 21:45:53233 is_authenticated_ = true;
[email protected]34df2ab2012-08-19 06:54:23234
[email protected]5dc5b12a2012-06-23 01:05:14235 if (max_duration_ > base::TimeDelta()) {
sergeyuec77d8542015-11-03 22:31:00236 max_duration_timer_.Start(
237 FROM_HERE, max_duration_,
238 base::Bind(&ClientSession::DisconnectSession, base::Unretained(this),
239 protocol::MAX_SESSION_LENGTH));
[email protected]5dc5b12a2012-06-23 01:05:14240 }
[email protected]34df2ab2012-08-19 06:54:23241
sergeyu21c899e2015-11-24 16:39:55242 // Notify EventHandler.
243 event_handler_->OnSessionAuthenticated(this);
[email protected]ce404ca2013-01-16 17:23:53244
zijiehef38c9722017-02-08 02:05:29245 DesktopEnvironmentOptions options = desktop_environment_options_;
246 options.ApplyHostSessionOptions(HostSessionOptions(
247 host_experiment_session_plugin_.configuration()));
[email protected]96361d02013-05-08 18:26:18248 // Create the desktop environment. Drop the connection if it could not be
249 // created for any reason (for instance the curtain could not initialize).
zijiehef38c9722017-02-08 02:05:29250 desktop_environment_ =
251 desktop_environment_factory_->Create(weak_factory_.GetWeakPtr(), options);
[email protected]96361d02013-05-08 18:26:18252 if (!desktop_environment_) {
sergeyuec77d8542015-11-03 22:31:00253 DisconnectSession(protocol::HOST_CONFIGURATION_ERROR);
[email protected]96361d02013-05-08 18:26:18254 return;
255 }
256
sergeyu1f8cd502015-02-13 21:45:53257 // Connect host stub.
258 connection_->set_host_stub(this);
259
[email protected]1b478ba2014-07-31 12:51:43260 // Collate the set of capabilities to offer the client, if it supports them.
sergeyuf69b019f2014-09-13 20:41:02261 host_capabilities_ = desktop_environment_->GetCapabilities();
262 if (!host_capabilities_.empty())
263 host_capabilities_.append(" ");
264 host_capabilities_.append(extension_manager_->GetCapabilities());
[email protected]233bb942013-03-15 07:18:17265
[email protected]231316a2013-03-25 06:01:12266 // Create the object that controls the screen resolution.
267 screen_controls_ = desktop_environment_->CreateScreenControls();
[email protected]61cfdc52013-03-09 03:04:56268
[email protected]324b1962013-05-01 19:30:22269 // Create the event executor.
[email protected]231316a2013-03-25 06:01:12270 input_injector_ = desktop_environment_->CreateInputInjector();
[email protected]eccc2d42013-01-10 19:35:14271
sergeyu1f8cd502015-02-13 21:45:53272 // Connect the host input stubs.
273 connection_->set_input_stub(&disable_input_filter_);
[email protected]b0b72f112013-03-24 03:42:42274 host_input_filter_.set_input_stub(input_injector_.get());
sergeyu1f8cd502015-02-13 21:45:53275
276 // Connect the clipboard stubs.
277 connection_->set_clipboard_stub(&disable_clipboard_filter_);
[email protected]b0b72f112013-03-24 03:42:42278 clipboard_echo_filter_.set_host_stub(input_injector_.get());
sergeyu1f8cd502015-02-13 21:45:53279 clipboard_echo_filter_.set_client_stub(connection_->client_stub());
[email protected]324b1962013-05-01 19:30:22280}
281
sergeyu4e1f4cd2016-09-27 00:42:52282void ClientSession::CreateMediaStreams() {
gabbf77513a2017-06-01 14:35:34283 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
sergeyu9102cff2016-04-07 19:14:01284
285 // Create a VideoStream to pump frames from the capturer to the client.
286 video_stream_ = connection_->StartVideoStream(
287 desktop_environment_->CreateVideoCapturer());
288
sergeyucd16e2062016-09-12 19:28:35289 // Create a AudioStream to pump audio from the capturer to the client.
sergeyuefb565c2016-10-11 15:29:01290 std::unique_ptr<protocol::AudioSource> audio_capturer =
291 desktop_environment_->CreateAudioCapturer();
292 if (audio_capturer) {
293 audio_stream_ = connection_->StartAudioStream(std::move(audio_capturer));
294 }
sergeyucd16e2062016-09-12 19:28:35295
sergeyuad51be82016-06-22 06:04:39296 video_stream_->SetObserver(this);
sergeyu9102cff2016-04-07 19:14:01297
298 // Apply video-control parameters to the new stream.
299 video_stream_->SetLosslessEncode(lossless_video_encode_);
300 video_stream_->SetLosslessColor(lossless_video_color_);
301
302 // Pause capturing if necessary.
303 video_stream_->Pause(pause_video_);
sergeyub047307a2016-10-18 17:19:29304
305 if (event_timestamp_source_for_tests_)
306 video_stream_->SetEventTimestampsSource(event_timestamp_source_for_tests_);
sergeyu9102cff2016-04-07 19:14:01307}
308
sergeyu4e1f4cd2016-09-27 00:42:52309void ClientSession::OnConnectionChannelsConnected() {
gabbf77513a2017-06-01 14:35:34310 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]324b1962013-05-01 19:30:22311
sergeyu9102cff2016-04-07 19:14:01312 DCHECK(!channels_connected_);
313 channels_connected_ = true;
314
[email protected]324b1962013-05-01 19:30:22315 // Negotiate capabilities with the client.
sergeyuf69b019f2014-09-13 20:41:02316 VLOG(1) << "Host capabilities: " << host_capabilities_;
sergeyuf69b019f2014-09-13 20:41:02317 protocol::Capabilities capabilities;
318 capabilities.set_capabilities(host_capabilities_);
319 connection_->client_stub()->SetCapabilities(capabilities);
[email protected]324b1962013-05-01 19:30:22320
321 // Start the event executor.
322 input_injector_->Start(CreateClipboardProxy());
323 SetDisableInputs(false);
324
sergeyu6ad12dc2016-04-02 00:01:32325 // Create MouseShapePump to send mouse cursor shape.
326 mouse_shape_pump_.reset(
327 new MouseShapePump(desktop_environment_->CreateMouseCursorMonitor(),
328 connection_->client_stub()));
329
sergeyu9102cff2016-04-07 19:14:01330 if (pending_video_layout_message_) {
331 connection_->client_stub()->SetVideoLayout(*pending_video_layout_message_);
332 pending_video_layout_message_.reset();
333 }
334
[email protected]cdd1c9e2012-10-26 21:14:04335 // Notify the event handler that all our channels are now connected.
[email protected]cba6f812012-03-27 01:01:50336 event_handler_->OnSessionChannelsConnected(this);
[email protected]ee910fd2011-11-10 18:23:31337}
338
sergeyu4e1f4cd2016-09-27 00:42:52339void ClientSession::OnConnectionClosed(protocol::ErrorCode error) {
gabbf77513a2017-06-01 14:35:34340 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]750ae6b2012-08-20 22:52:40341
lukaszaf34d8412015-04-30 23:09:59342 HOST_LOG << "Client disconnected: " << client_jid_ << "; error = " << error;
343
[email protected]231316a2013-03-25 06:01:12344 // Ignore any further callbacks.
kulkarni.a933aeaf2014-09-20 13:19:17345 weak_factory_.InvalidateWeakPtrs();
[email protected]a031c972012-12-27 20:10:40346
[email protected]24a2a9d22012-12-07 09:06:47347 // If the client never authenticated then the session failed.
sergeyu1f8cd502015-02-13 21:45:53348 if (!is_authenticated_)
[email protected]1f249e22011-11-29 20:19:59349 event_handler_->OnSessionAuthenticationFailed(this);
[email protected]750ae6b2012-08-20 22:52:40350
[email protected]86cbe6b2012-04-03 00:56:18351 // Ensure that any pressed keys or buttons are released.
352 input_tracker_.ReleaseAll();
353
[email protected]24a2a9d22012-12-07 09:06:47354 // Stop components access the client, audio or video stubs, which are no
355 // longer valid once ConnectionToClient calls OnConnectionClosed().
sergeyucd16e2062016-09-12 19:28:35356 audio_stream_.reset();
sergeyua609b7a2015-11-30 06:25:39357 video_stream_.reset();
sergeyu1afb35a12015-02-13 18:45:30358 mouse_shape_pump_.reset();
[email protected]24a2a9d22012-12-07 09:06:47359 client_clipboard_factory_.InvalidateWeakPtrs();
[email protected]b0b72f112013-03-24 03:42:42360 input_injector_.reset();
[email protected]231316a2013-03-25 06:01:12361 screen_controls_.reset();
362 desktop_environment_.reset();
[email protected]24a2a9d22012-12-07 09:06:47363
364 // Notify the ChromotingHost that this client is disconnected.
[email protected]ee910fd2011-11-10 18:23:31365 event_handler_->OnSessionClosed(this);
[email protected]ee910fd2011-11-10 18:23:31366}
367
[email protected]17af2ab2012-02-02 04:07:52368void ClientSession::OnRouteChange(
[email protected]17af2ab2012-02-02 04:07:52369 const std::string& channel_name,
[email protected]be451c82012-03-20 22:24:47370 const protocol::TransportRoute& route) {
gabbf77513a2017-06-01 14:35:34371 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]be451c82012-03-20 22:24:47372 event_handler_->OnSessionRouteChange(this, channel_name, route);
[email protected]91e4b7f62012-01-25 23:23:02373}
374
[email protected]231316a2013-03-25 06:01:12375const std::string& ClientSession::client_jid() const {
376 return client_jid_;
377}
378
sergeyuec77d8542015-11-03 22:31:00379void ClientSession::DisconnectSession(protocol::ErrorCode error) {
gabbf77513a2017-06-01 14:35:34380 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]ec6411872011-11-11 03:28:55381 DCHECK(connection_.get());
[email protected]a46bcef2011-11-11 01:27:23382
[email protected]5dc5b12a2012-06-23 01:05:14383 max_duration_timer_.Stop();
[email protected]24a2a9d22012-12-07 09:06:47384
[email protected]86cbe6b2012-04-03 00:56:18385 // This triggers OnConnectionClosed(), and the session may be destroyed
[email protected]a46bcef2011-11-11 01:27:23386 // as the result, so this call must be the last in this method.
sergeyuec77d8542015-11-03 22:31:00387 connection_->Disconnect(error);
[email protected]44f60762011-03-23 12:13:35388}
389
[email protected]8c83a71c2013-12-16 18:02:58390void ClientSession::OnLocalMouseMoved(const webrtc::DesktopVector& position) {
gabbf77513a2017-06-01 14:35:34391 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]231316a2013-03-25 06:01:12392 remote_input_filter_.LocalMouseMoved(position);
[email protected]86cbe6b2012-04-03 00:56:18393}
[email protected]ec6411872011-11-11 03:28:55394
[email protected]86cbe6b2012-04-03 00:56:18395void ClientSession::SetDisableInputs(bool disable_inputs) {
gabbf77513a2017-06-01 14:35:34396 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]86cbe6b2012-04-03 00:56:18397
[email protected]750ae6b2012-08-20 22:52:40398 if (disable_inputs)
[email protected]86cbe6b2012-04-03 00:56:18399 input_tracker_.ReleaseAll();
[email protected]750ae6b2012-08-20 22:52:40400
401 disable_input_filter_.set_enabled(!disable_inputs);
402 disable_clipboard_filter_.set_enabled(!disable_inputs);
[email protected]c78669c92011-06-13 22:42:38403}
404
joedow4fa09d92016-06-27 21:26:17405uint32_t ClientSession::desktop_session_id() const {
gabbf77513a2017-06-01 14:35:34406 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
joedow4fa09d92016-06-27 21:26:17407 DCHECK(desktop_environment_);
408 return desktop_environment_->GetDesktopSessionId();
409}
410
411ClientSessionControl* ClientSession::session_control() {
gabbf77513a2017-06-01 14:35:34412 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
joedow4fa09d92016-06-27 21:26:17413 return this;
414}
415
sergeyub047307a2016-10-18 17:19:29416void ClientSession::SetEventTimestampsSourceForTests(
417 scoped_refptr<protocol::InputEventTimestampsSource>
418 event_timestamp_source) {
gabbf77513a2017-06-01 14:35:34419 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
sergeyub047307a2016-10-18 17:19:29420 event_timestamp_source_for_tests_ = event_timestamp_source;
421 if (video_stream_)
422 video_stream_->SetEventTimestampsSource(event_timestamp_source_for_tests_);
423}
424
dcheng0765c492016-04-06 22:41:53425std::unique_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() {
gabbf77513a2017-06-01 14:35:34426 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ricea68860bd2016-08-22 02:48:56427 return base::MakeUnique<protocol::ClipboardThreadProxy>(
428 client_clipboard_factory_.GetWeakPtr(),
429 base::ThreadTaskRunnerHandle::Get());
[email protected]7f44ba42012-05-31 20:26:29430}
431
sergeyuad51be82016-06-22 06:04:39432void ClientSession::OnVideoSizeChanged(protocol::VideoStream* video_stream,
433 const webrtc::DesktopSize& size,
434 const webrtc::DesktopVector& dpi) {
gabbf77513a2017-06-01 14:35:34435 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
sergeyu00a67b12016-04-01 00:07:00436
sergeyua609b7a2015-11-30 06:25:39437 mouse_clamping_filter_.set_output_size(size);
sergeyu00a67b12016-04-01 00:07:00438
sergeyuf8170a392016-04-08 22:12:19439 switch (connection_->session()->config().protocol()) {
440 case protocol::SessionConfig::Protocol::ICE:
441 mouse_clamping_filter_.set_input_size(size);
442 break;
sergeyu9102cff2016-04-07 19:14:01443
sergeyuf8170a392016-04-08 22:12:19444 case protocol::SessionConfig::Protocol::WEBRTC: {
445 // When using WebRTC protocol the client sends mouse coordinates in DIPs,
446 // while InputInjector expects them in physical pixels.
447 // TODO(sergeyu): Fix InputInjector implementations to use DIPs as well.
448 webrtc::DesktopSize size_dips(size.width() * kDefaultDpi / dpi.x(),
449 size.height() * kDefaultDpi / dpi.y());
450 mouse_clamping_filter_.set_input_size(size_dips);
451
452 // Generate and send VideoLayout message.
453 protocol::VideoLayout layout;
454 protocol::VideoTrackLayout* video_track = layout.add_video_track();
455 video_track->set_position_x(0);
456 video_track->set_position_y(0);
457 video_track->set_width(size_dips.width());
458 video_track->set_height(size_dips.height());
459 video_track->set_x_dpi(dpi.x());
460 video_track->set_y_dpi(dpi.y());
461
462 // VideoLayout can be sent only after the control channel is connected.
463 // TODO(sergeyu): Change client_stub() implementation to allow queuing
464 // while connection is being established.
465 if (channels_connected_) {
466 connection_->client_stub()->SetVideoLayout(layout);
467 } else {
468 pending_video_layout_message_.reset(new protocol::VideoLayout(layout));
469 }
470 break;
sergeyu9102cff2016-04-07 19:14:01471 }
sergeyu00a67b12016-04-01 00:07:00472 }
sergeyua609b7a2015-11-30 06:25:39473}
474
[email protected]44f60762011-03-23 12:13:35475} // namespace remoting