[email protected] | 91e4b7f6 | 2012-01-25 23:23:02 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "remoting/host/client_session.h" |
| 6 | |
[email protected] | 4fe827a | 2011-08-10 03:30:19 | [diff] [blame] | 7 | #include <algorithm> |
sergeyu | 1417e013 | 2015-12-23 19:01:22 | [diff] [blame] | 8 | #include <utility> |
[email protected] | 4fe827a | 2011-08-10 03:30:19 | [diff] [blame] | 9 | |
wez | 43ac266 | 2015-06-10 18:22:29 | [diff] [blame] | 10 | #include "base/command_line.h" |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame^] | 11 | #include "base/memory/ptr_util.h" |
anujk.sharma | bb80293 | 2015-05-05 21:57:29 | [diff] [blame] | 12 | #include "base/single_thread_task_runner.h" |
| 13 | #include "base/thread_task_runner_handle.h" |
avi | c5960f3 | 2015-12-22 22:49:48 | [diff] [blame] | 14 | #include "build/build_config.h" |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 15 | #include "remoting/base/capabilities.h" |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 16 | #include "remoting/base/constants.h" |
[email protected] | 6f742dd0 | 2013-11-26 23:19:50 | [diff] [blame] | 17 | #include "remoting/base/logging.h" |
[email protected] | 170cba4 | 2012-09-12 22:28:39 | [diff] [blame] | 18 | #include "remoting/codec/audio_encoder.h" |
[email protected] | a6ccb772 | 2012-10-23 21:10:43 | [diff] [blame] | 19 | #include "remoting/codec/audio_encoder_opus.h" |
[email protected] | 170cba4 | 2012-09-12 22:28:39 | [diff] [blame] | 20 | #include "remoting/codec/audio_encoder_verbatim.h" |
[email protected] | ce404ca | 2013-01-16 17:23:53 | [diff] [blame] | 21 | #include "remoting/host/audio_capturer.h" |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 22 | #include "remoting/host/audio_pump.h" |
[email protected] | 170cba4 | 2012-09-12 22:28:39 | [diff] [blame] | 23 | #include "remoting/host/desktop_environment.h" |
[email protected] | 399b4f6 | 2014-05-30 20:13:15 | [diff] [blame] | 24 | #include "remoting/host/host_extension_session.h" |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 25 | #include "remoting/host/input_injector.h" |
sergeyu | 1afb35a1 | 2015-02-13 18:45:30 | [diff] [blame] | 26 | #include "remoting/host/mouse_shape_pump.h" |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 27 | #include "remoting/host/screen_controls.h" |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 28 | #include "remoting/host/screen_resolution.h" |
[email protected] | 50d71c7 | 2012-05-03 01:28:55 | [diff] [blame] | 29 | #include "remoting/proto/control.pb.h" |
[email protected] | c78669c9 | 2011-06-13 22:42:38 | [diff] [blame] | 30 | #include "remoting/proto/event.pb.h" |
[email protected] | ff3761a1 | 2012-05-22 22:29:24 | [diff] [blame] | 31 | #include "remoting/protocol/client_stub.h" |
[email protected] | 7f44ba4 | 2012-05-31 20:26:29 | [diff] [blame] | 32 | #include "remoting/protocol/clipboard_thread_proxy.h" |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 33 | #include "remoting/protocol/pairing_registry.h" |
sergeyu | b031cd2 | 2015-11-19 22:17:13 | [diff] [blame] | 34 | #include "remoting/protocol/session.h" |
| 35 | #include "remoting/protocol/session_config.h" |
sergeyu | 4d20800 | 2015-11-23 22:27:43 | [diff] [blame] | 36 | #include "remoting/protocol/video_frame_pump.h" |
[email protected] | 4e719f4 | 2014-08-12 18:04:37 | [diff] [blame] | 37 | #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" |
[email protected] | c78669c9 | 2011-06-13 22:42:38 | [diff] [blame] | 38 | |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 39 | namespace remoting { |
[email protected] | 48a8ca3 | 2013-02-13 04:31:01 | [diff] [blame] | 40 | |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 41 | namespace { |
| 42 | |
wez | 6e95a37 | 2015-07-08 22:33:31 | [diff] [blame] | 43 | // Name of command-line flag to disable use of I444 by default. |
| 44 | const char kDisableI444SwitchName[] = "disable-i444"; |
wez | 43ac266 | 2015-06-10 18:22:29 | [diff] [blame] | 45 | |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame^] | 46 | std::unique_ptr<AudioEncoder> CreateAudioEncoder( |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 47 | const protocol::SessionConfig& config) { |
| 48 | const protocol::ChannelConfig& audio_config = config.audio_config(); |
| 49 | |
| 50 | if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame^] | 51 | return base::WrapUnique(new AudioEncoderVerbatim()); |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 52 | } else if (audio_config.codec == protocol::ChannelConfig::CODEC_OPUS) { |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame^] | 53 | return base::WrapUnique(new AudioEncoderOpus()); |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 54 | } |
| 55 | |
| 56 | NOTREACHED(); |
| 57 | return nullptr; |
| 58 | } |
| 59 | |
| 60 | } // namespace |
| 61 | |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 62 | ClientSession::ClientSession( |
| 63 | EventHandler* event_handler, |
[email protected] | 032d9dd | 2012-11-01 17:55:04 | [diff] [blame] | 64 | scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner, |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame^] | 65 | std::unique_ptr<protocol::ConnectionToClient> connection, |
[email protected] | 8190479 | 2012-10-18 04:16:28 | [diff] [blame] | 66 | DesktopEnvironmentFactory* desktop_environment_factory, |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 67 | const base::TimeDelta& max_duration, |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 68 | scoped_refptr<protocol::PairingRegistry> pairing_registry, |
| 69 | const std::vector<HostExtension*>& extensions) |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 70 | : event_handler_(event_handler), |
sergeyu | 1417e013 | 2015-12-23 19:01:22 | [diff] [blame] | 71 | connection_(std::move(connection)), |
[email protected] | 3361e1f | 2012-03-20 20:31:44 | [diff] [blame] | 72 | client_jid_(connection_->session()->jid()), |
[email protected] | 233bb94 | 2013-03-15 07:18:17 | [diff] [blame] | 73 | desktop_environment_factory_(desktop_environment_factory), |
[email protected] | eccc2d4 | 2013-01-10 19:35:14 | [diff] [blame] | 74 | input_tracker_(&host_input_filter_), |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 75 | remote_input_filter_(&input_tracker_), |
[email protected] | 58f1ad4 | 2013-01-10 23:49:51 | [diff] [blame] | 76 | mouse_clamping_filter_(&remote_input_filter_), |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 77 | disable_input_filter_(&mouse_clamping_filter_), |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 78 | disable_clipboard_filter_(clipboard_echo_filter_.host_filter()), |
[email protected] | 7f44ba4 | 2012-05-31 20:26:29 | [diff] [blame] | 79 | client_clipboard_factory_(clipboard_echo_filter_.client_filter()), |
[email protected] | 170cba4 | 2012-09-12 22:28:39 | [diff] [blame] | 80 | max_duration_(max_duration), |
[email protected] | 032d9dd | 2012-11-01 17:55:04 | [diff] [blame] | 81 | audio_task_runner_(audio_task_runner), |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 82 | pairing_registry_(pairing_registry), |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 83 | is_authenticated_(false), |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 84 | pause_video_(false), |
| 85 | lossless_video_encode_(false), |
wez | 6e95a37 | 2015-07-08 22:33:31 | [diff] [blame] | 86 | // Note that |lossless_video_color_| defaults to true, but actually only |
| 87 | // controls VP9 video stream color quality. |
| 88 | lossless_video_color_(!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 89 | kDisableI444SwitchName)), |
kulkarni.a | 933aeaf | 2014-09-20 13:19:17 | [diff] [blame] | 90 | weak_factory_(this) { |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 91 | connection_->SetEventHandler(this); |
| 92 | |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 93 | // Create a manager for the configured extensions, if any. |
| 94 | extension_manager_.reset(new HostExtensionSessionManager(extensions, this)); |
| 95 | |
[email protected] | 2f408489 | 2013-02-25 20:30:20 | [diff] [blame] | 96 | #if defined(OS_WIN) |
| 97 | // LocalInputMonitorWin filters out an echo of the injected input before it |
| 98 | // reaches |remote_input_filter_|. |
| 99 | remote_input_filter_.SetExpectLocalEcho(false); |
| 100 | #endif // defined(OS_WIN) |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 101 | } |
| 102 | |
[email protected] | f19f09ca | 2013-03-13 11:10:29 | [diff] [blame] | 103 | ClientSession::~ClientSession() { |
| 104 | DCHECK(CalledOnValidThread()); |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 105 | DCHECK(!audio_pump_); |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 106 | DCHECK(!desktop_environment_); |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 107 | DCHECK(!input_injector_); |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 108 | DCHECK(!screen_controls_); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 109 | DCHECK(!video_stream_); |
[email protected] | f19f09ca | 2013-03-13 11:10:29 | [diff] [blame] | 110 | |
| 111 | connection_.reset(); |
| 112 | } |
| 113 | |
[email protected] | 48a8ca3 | 2013-02-13 04:31:01 | [diff] [blame] | 114 | void ClientSession::NotifyClientResolution( |
| 115 | const protocol::ClientResolution& resolution) { |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 116 | DCHECK(CalledOnValidThread()); |
| 117 | |
[email protected] | b9ed58f | 2013-05-16 10:45:24 | [diff] [blame] | 118 | // TODO(sergeyu): Move these checks to protocol layer. |
| 119 | if (!resolution.has_dips_width() || !resolution.has_dips_height() || |
| 120 | resolution.dips_width() < 0 || resolution.dips_height() < 0 || |
| 121 | resolution.width() <= 0 || resolution.height() <= 0) { |
| 122 | LOG(ERROR) << "Received invalid ClientResolution message."; |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 123 | return; |
[email protected] | b9ed58f | 2013-05-16 10:45:24 | [diff] [blame] | 124 | } |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 125 | |
| 126 | VLOG(1) << "Received ClientResolution (dips_width=" |
| 127 | << resolution.dips_width() << ", dips_height=" |
| 128 | << resolution.dips_height() << ")"; |
| 129 | |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 130 | if (!screen_controls_) |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 131 | return; |
| 132 | |
| 133 | ScreenResolution client_resolution( |
[email protected] | b9ed58f | 2013-05-16 10:45:24 | [diff] [blame] | 134 | webrtc::DesktopSize(resolution.dips_width(), resolution.dips_height()), |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 135 | webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)); |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 136 | |
| 137 | // Try to match the client's resolution. |
[email protected] | b9ed58f | 2013-05-16 10:45:24 | [diff] [blame] | 138 | screen_controls_->SetScreenResolution(client_resolution); |
[email protected] | 50d71c7 | 2012-05-03 01:28:55 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | void ClientSession::ControlVideo(const protocol::VideoControl& video_control) { |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 142 | DCHECK(CalledOnValidThread()); |
| 143 | |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 144 | // Note that |video_stream_| may be null, depending upon whether |
sergeyu | 10ce97b | 2015-02-05 23:53:14 | [diff] [blame] | 145 | // extensions choose to wrap or "steal" the video capturer or encoder. |
[email protected] | 50d71c7 | 2012-05-03 01:28:55 | [diff] [blame] | 146 | if (video_control.has_enable()) { |
| 147 | VLOG(1) << "Received VideoControl (enable=" |
| 148 | << video_control.enable() << ")"; |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 149 | pause_video_ = !video_control.enable(); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 150 | if (video_stream_) |
| 151 | video_stream_->Pause(pause_video_); |
[email protected] | 50d71c7 | 2012-05-03 01:28:55 | [diff] [blame] | 152 | } |
[email protected] | a516f1e | 2014-05-30 07:21:20 | [diff] [blame] | 153 | if (video_control.has_lossless_encode()) { |
| 154 | VLOG(1) << "Received VideoControl (lossless_encode=" |
| 155 | << video_control.lossless_encode() << ")"; |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 156 | lossless_video_encode_ = video_control.lossless_encode(); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 157 | if (video_stream_) |
| 158 | video_stream_->SetLosslessEncode(lossless_video_encode_); |
[email protected] | a516f1e | 2014-05-30 07:21:20 | [diff] [blame] | 159 | } |
| 160 | if (video_control.has_lossless_color()) { |
| 161 | VLOG(1) << "Received VideoControl (lossless_color=" |
| 162 | << video_control.lossless_color() << ")"; |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 163 | lossless_video_color_ = video_control.lossless_color(); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 164 | if (video_stream_) |
| 165 | video_stream_->SetLosslessColor(lossless_video_color_); |
[email protected] | a516f1e | 2014-05-30 07:21:20 | [diff] [blame] | 166 | } |
[email protected] | f2b9cf3 | 2012-04-27 00:13:43 | [diff] [blame] | 167 | } |
| 168 | |
[email protected] | f458bed | 2012-10-18 03:27:59 | [diff] [blame] | 169 | void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) { |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 170 | DCHECK(CalledOnValidThread()); |
| 171 | |
[email protected] | f458bed | 2012-10-18 03:27:59 | [diff] [blame] | 172 | if (audio_control.has_enable()) { |
| 173 | VLOG(1) << "Received AudioControl (enable=" |
| 174 | << audio_control.enable() << ")"; |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 175 | if (audio_pump_) |
| 176 | audio_pump_->Pause(!audio_control.enable()); |
[email protected] | f458bed | 2012-10-18 03:27:59 | [diff] [blame] | 177 | } |
| 178 | } |
| 179 | |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 180 | void ClientSession::SetCapabilities( |
| 181 | const protocol::Capabilities& capabilities) { |
| 182 | DCHECK(CalledOnValidThread()); |
| 183 | |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 184 | // Ignore all the messages but the 1st one. |
| 185 | if (client_capabilities_) { |
| 186 | LOG(WARNING) << "protocol::Capabilities has been received already."; |
| 187 | return; |
| 188 | } |
| 189 | |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 190 | // Compute the set of capabilities supported by both client and host. |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame^] | 191 | client_capabilities_ = base::WrapUnique(new std::string()); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 192 | if (capabilities.has_capabilities()) |
| 193 | *client_capabilities_ = capabilities.capabilities(); |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 194 | capabilities_ = IntersectCapabilities(*client_capabilities_, |
| 195 | host_capabilities_); |
| 196 | extension_manager_->OnNegotiatedCapabilities( |
| 197 | connection_->client_stub(), capabilities_); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 198 | |
| 199 | VLOG(1) << "Client capabilities: " << *client_capabilities_; |
| 200 | |
| 201 | // Calculate the set of capabilities enabled by both client and host and |
| 202 | // pass it to the desktop environment if it is available. |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 203 | desktop_environment_->SetCapabilities(capabilities_); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 204 | } |
| 205 | |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 206 | void ClientSession::RequestPairing( |
| 207 | const protocol::PairingRequest& pairing_request) { |
dcheng | ac10e4a8 | 2014-08-26 03:53:44 | [diff] [blame] | 208 | if (pairing_registry_.get() && pairing_request.has_client_name()) { |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 209 | protocol::PairingRegistry::Pairing pairing = |
| 210 | pairing_registry_->CreatePairing(pairing_request.client_name()); |
| 211 | protocol::PairingResponse pairing_response; |
[email protected] | df5189f | 2013-06-18 12:12:05 | [diff] [blame] | 212 | pairing_response.set_client_id(pairing.client_id()); |
| 213 | pairing_response.set_shared_secret(pairing.shared_secret()); |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 214 | connection_->client_stub()->SetPairingResponse(pairing_response); |
| 215 | } |
| 216 | } |
| 217 | |
[email protected] | 09eabd65c | 2013-08-13 00:13:48 | [diff] [blame] | 218 | void ClientSession::DeliverClientMessage( |
| 219 | const protocol::ExtensionMessage& message) { |
[email protected] | af278c4 | 2013-09-02 05:27:00 | [diff] [blame] | 220 | if (message.has_type()) { |
| 221 | if (message.type() == "test-echo") { |
| 222 | protocol::ExtensionMessage reply; |
| 223 | reply.set_type("test-echo-reply"); |
| 224 | if (message.has_data()) |
| 225 | reply.set_data(message.data().substr(0, 16)); |
| 226 | connection_->client_stub()->DeliverHostMessage(reply); |
| 227 | return; |
[email protected] | 399b4f6 | 2014-05-30 20:13:15 | [diff] [blame] | 228 | } else { |
wez | 73f19de | 2014-10-29 19:06:33 | [diff] [blame] | 229 | if (extension_manager_->OnExtensionMessage(message)) |
wez | 8703699 | 2014-09-05 00:53:43 | [diff] [blame] | 230 | return; |
| 231 | |
| 232 | DLOG(INFO) << "Unexpected message received: " |
| 233 | << message.type() << ": " << message.data(); |
[email protected] | af278c4 | 2013-09-02 05:27:00 | [diff] [blame] | 234 | } |
| 235 | } |
[email protected] | 09eabd65c | 2013-08-13 00:13:48 | [diff] [blame] | 236 | } |
| 237 | |
[email protected] | 064128c | 2014-04-07 22:33:28 | [diff] [blame] | 238 | void ClientSession::OnConnectionAuthenticating( |
| 239 | protocol::ConnectionToClient* connection) { |
| 240 | event_handler_->OnSessionAuthenticating(this); |
| 241 | } |
| 242 | |
[email protected] | cba6f81 | 2012-03-27 01:01:50 | [diff] [blame] | 243 | void ClientSession::OnConnectionAuthenticated( |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 244 | protocol::ConnectionToClient* connection) { |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 245 | DCHECK(CalledOnValidThread()); |
| 246 | DCHECK_EQ(connection_.get(), connection); |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 247 | DCHECK(!audio_pump_); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 248 | DCHECK(!desktop_environment_); |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 249 | DCHECK(!input_injector_); |
| 250 | DCHECK(!screen_controls_); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 251 | DCHECK(!video_stream_); |
[email protected] | 34df2ab | 2012-08-19 06:54:23 | [diff] [blame] | 252 | |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 253 | is_authenticated_ = true; |
[email protected] | 34df2ab | 2012-08-19 06:54:23 | [diff] [blame] | 254 | |
[email protected] | 5dc5b12a | 2012-06-23 01:05:14 | [diff] [blame] | 255 | if (max_duration_ > base::TimeDelta()) { |
sergeyu | ec77d854 | 2015-11-03 22:31:00 | [diff] [blame] | 256 | max_duration_timer_.Start( |
| 257 | FROM_HERE, max_duration_, |
| 258 | base::Bind(&ClientSession::DisconnectSession, base::Unretained(this), |
| 259 | protocol::MAX_SESSION_LENGTH)); |
[email protected] | 5dc5b12a | 2012-06-23 01:05:14 | [diff] [blame] | 260 | } |
[email protected] | 34df2ab | 2012-08-19 06:54:23 | [diff] [blame] | 261 | |
sergeyu | 21c899e | 2015-11-24 16:39:55 | [diff] [blame] | 262 | // Notify EventHandler. |
| 263 | event_handler_->OnSessionAuthenticated(this); |
[email protected] | ce404ca | 2013-01-16 17:23:53 | [diff] [blame] | 264 | |
[email protected] | 96361d0 | 2013-05-08 18:26:18 | [diff] [blame] | 265 | // Create the desktop environment. Drop the connection if it could not be |
| 266 | // created for any reason (for instance the curtain could not initialize). |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 267 | desktop_environment_ = |
kulkarni.a | 933aeaf | 2014-09-20 13:19:17 | [diff] [blame] | 268 | desktop_environment_factory_->Create(weak_factory_.GetWeakPtr()); |
[email protected] | 96361d0 | 2013-05-08 18:26:18 | [diff] [blame] | 269 | if (!desktop_environment_) { |
sergeyu | ec77d854 | 2015-11-03 22:31:00 | [diff] [blame] | 270 | DisconnectSession(protocol::HOST_CONFIGURATION_ERROR); |
[email protected] | 96361d0 | 2013-05-08 18:26:18 | [diff] [blame] | 271 | return; |
| 272 | } |
| 273 | |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 274 | // Connect host stub. |
| 275 | connection_->set_host_stub(this); |
| 276 | |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 277 | // Collate the set of capabilities to offer the client, if it supports them. |
sergeyu | f69b019f | 2014-09-13 20:41:02 | [diff] [blame] | 278 | host_capabilities_ = desktop_environment_->GetCapabilities(); |
| 279 | if (!host_capabilities_.empty()) |
| 280 | host_capabilities_.append(" "); |
| 281 | host_capabilities_.append(extension_manager_->GetCapabilities()); |
[email protected] | 233bb94 | 2013-03-15 07:18:17 | [diff] [blame] | 282 | |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 283 | // Create the object that controls the screen resolution. |
| 284 | screen_controls_ = desktop_environment_->CreateScreenControls(); |
[email protected] | 61cfdc5 | 2013-03-09 03:04:56 | [diff] [blame] | 285 | |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 286 | // Create the event executor. |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 287 | input_injector_ = desktop_environment_->CreateInputInjector(); |
[email protected] | eccc2d4 | 2013-01-10 19:35:14 | [diff] [blame] | 288 | |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 289 | // Connect the host input stubs. |
| 290 | connection_->set_input_stub(&disable_input_filter_); |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 291 | host_input_filter_.set_input_stub(input_injector_.get()); |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 292 | |
| 293 | // Connect the clipboard stubs. |
| 294 | connection_->set_clipboard_stub(&disable_clipboard_filter_); |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 295 | clipboard_echo_filter_.set_host_stub(input_injector_.get()); |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 296 | clipboard_echo_filter_.set_client_stub(connection_->client_stub()); |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 297 | } |
| 298 | |
| 299 | void ClientSession::OnConnectionChannelsConnected( |
| 300 | protocol::ConnectionToClient* connection) { |
| 301 | DCHECK(CalledOnValidThread()); |
| 302 | DCHECK_EQ(connection_.get(), connection); |
| 303 | |
| 304 | // Negotiate capabilities with the client. |
sergeyu | f69b019f | 2014-09-13 20:41:02 | [diff] [blame] | 305 | VLOG(1) << "Host capabilities: " << host_capabilities_; |
sergeyu | f69b019f | 2014-09-13 20:41:02 | [diff] [blame] | 306 | protocol::Capabilities capabilities; |
| 307 | capabilities.set_capabilities(host_capabilities_); |
| 308 | connection_->client_stub()->SetCapabilities(capabilities); |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 309 | |
| 310 | // Start the event executor. |
| 311 | input_injector_->Start(CreateClipboardProxy()); |
| 312 | SetDisableInputs(false); |
| 313 | |
sergeyu | 6ad12dc | 2016-04-02 00:01:32 | [diff] [blame] | 314 | // Create MouseShapePump to send mouse cursor shape. |
| 315 | mouse_shape_pump_.reset( |
| 316 | new MouseShapePump(desktop_environment_->CreateMouseCursorMonitor(), |
| 317 | connection_->client_stub())); |
| 318 | |
| 319 | // Create a VideoStream to pump frames from the capturer to the client. |
| 320 | video_stream_ = connection_->StartVideoStream( |
| 321 | desktop_environment_->CreateVideoCapturer()); |
| 322 | |
| 323 | video_stream_->SetSizeCallback( |
| 324 | base::Bind(&ClientSession::OnScreenSizeChanged, base::Unretained(this))); |
| 325 | |
| 326 | // Apply video-control parameters to the new stream. |
| 327 | video_stream_->SetLosslessEncode(lossless_video_encode_); |
| 328 | video_stream_->SetLosslessColor(lossless_video_color_); |
| 329 | |
| 330 | // Pause capturing if necessary. |
| 331 | video_stream_->Pause(pause_video_); |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 332 | |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 333 | // Create an AudioPump if audio is enabled, to pump audio samples. |
| 334 | if (connection_->session()->config().is_audio_enabled()) { |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame^] | 335 | std::unique_ptr<AudioEncoder> audio_encoder = |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 336 | CreateAudioEncoder(connection_->session()->config()); |
| 337 | audio_pump_.reset(new AudioPump( |
| 338 | audio_task_runner_, desktop_environment_->CreateAudioCapturer(), |
sergeyu | 1417e013 | 2015-12-23 19:01:22 | [diff] [blame] | 339 | std::move(audio_encoder), connection_->audio_stub())); |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 340 | } |
[email protected] | 170cba4 | 2012-09-12 22:28:39 | [diff] [blame] | 341 | |
[email protected] | cdd1c9e | 2012-10-26 21:14:04 | [diff] [blame] | 342 | // Notify the event handler that all our channels are now connected. |
[email protected] | cba6f81 | 2012-03-27 01:01:50 | [diff] [blame] | 343 | event_handler_->OnSessionChannelsConnected(this); |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 344 | } |
| 345 | |
[email protected] | cba6f81 | 2012-03-27 01:01:50 | [diff] [blame] | 346 | void ClientSession::OnConnectionClosed( |
[email protected] | 1f249e2 | 2011-11-29 20:19:59 | [diff] [blame] | 347 | protocol::ConnectionToClient* connection, |
[email protected] | 204a9e3 | 2012-03-02 05:42:58 | [diff] [blame] | 348 | protocol::ErrorCode error) { |
[email protected] | ec641187 | 2011-11-11 03:28:55 | [diff] [blame] | 349 | DCHECK(CalledOnValidThread()); |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 350 | DCHECK_EQ(connection_.get(), connection); |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 351 | |
lukasza | f34d841 | 2015-04-30 23:09:59 | [diff] [blame] | 352 | HOST_LOG << "Client disconnected: " << client_jid_ << "; error = " << error; |
| 353 | |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 354 | // Ignore any further callbacks. |
kulkarni.a | 933aeaf | 2014-09-20 13:19:17 | [diff] [blame] | 355 | weak_factory_.InvalidateWeakPtrs(); |
[email protected] | a031c97 | 2012-12-27 20:10:40 | [diff] [blame] | 356 | |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 357 | // If the client never authenticated then the session failed. |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 358 | if (!is_authenticated_) |
[email protected] | 1f249e2 | 2011-11-29 20:19:59 | [diff] [blame] | 359 | event_handler_->OnSessionAuthenticationFailed(this); |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 360 | |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 361 | // Ensure that any pressed keys or buttons are released. |
| 362 | input_tracker_.ReleaseAll(); |
| 363 | |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 364 | // Stop components access the client, audio or video stubs, which are no |
| 365 | // longer valid once ConnectionToClient calls OnConnectionClosed(). |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 366 | audio_pump_.reset(); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 367 | video_stream_.reset(); |
sergeyu | 1afb35a1 | 2015-02-13 18:45:30 | [diff] [blame] | 368 | mouse_shape_pump_.reset(); |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 369 | client_clipboard_factory_.InvalidateWeakPtrs(); |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 370 | input_injector_.reset(); |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 371 | screen_controls_.reset(); |
| 372 | desktop_environment_.reset(); |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 373 | |
| 374 | // Notify the ChromotingHost that this client is disconnected. |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 375 | event_handler_->OnSessionClosed(this); |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 376 | } |
| 377 | |
sergeyu | 752c6e6 | 2015-09-30 06:40:27 | [diff] [blame] | 378 | void ClientSession::OnInputEventReceived( |
| 379 | protocol::ConnectionToClient* connection, |
| 380 | int64_t event_timestamp) { |
[email protected] | ec641187 | 2011-11-11 03:28:55 | [diff] [blame] | 381 | DCHECK(CalledOnValidThread()); |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 382 | DCHECK_EQ(connection_.get(), connection); |
[email protected] | 170cba4 | 2012-09-12 22:28:39 | [diff] [blame] | 383 | |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 384 | if (video_stream_.get()) |
| 385 | video_stream_->OnInputEventReceived(event_timestamp); |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 386 | } |
| 387 | |
[email protected] | 17af2ab | 2012-02-02 04:07:52 | [diff] [blame] | 388 | void ClientSession::OnRouteChange( |
| 389 | protocol::ConnectionToClient* connection, |
| 390 | const std::string& channel_name, |
[email protected] | be451c8 | 2012-03-20 22:24:47 | [diff] [blame] | 391 | const protocol::TransportRoute& route) { |
[email protected] | 91e4b7f6 | 2012-01-25 23:23:02 | [diff] [blame] | 392 | DCHECK(CalledOnValidThread()); |
| 393 | DCHECK_EQ(connection_.get(), connection); |
[email protected] | be451c8 | 2012-03-20 22:24:47 | [diff] [blame] | 394 | event_handler_->OnSessionRouteChange(this, channel_name, route); |
[email protected] | 91e4b7f6 | 2012-01-25 23:23:02 | [diff] [blame] | 395 | } |
| 396 | |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 397 | const std::string& ClientSession::client_jid() const { |
| 398 | return client_jid_; |
| 399 | } |
| 400 | |
sergeyu | ec77d854 | 2015-11-03 22:31:00 | [diff] [blame] | 401 | void ClientSession::DisconnectSession(protocol::ErrorCode error) { |
[email protected] | ec641187 | 2011-11-11 03:28:55 | [diff] [blame] | 402 | DCHECK(CalledOnValidThread()); |
| 403 | DCHECK(connection_.get()); |
[email protected] | a46bcef | 2011-11-11 01:27:23 | [diff] [blame] | 404 | |
[email protected] | 5dc5b12a | 2012-06-23 01:05:14 | [diff] [blame] | 405 | max_duration_timer_.Stop(); |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 406 | |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 407 | // This triggers OnConnectionClosed(), and the session may be destroyed |
[email protected] | a46bcef | 2011-11-11 01:27:23 | [diff] [blame] | 408 | // as the result, so this call must be the last in this method. |
sergeyu | ec77d854 | 2015-11-03 22:31:00 | [diff] [blame] | 409 | connection_->Disconnect(error); |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 410 | } |
| 411 | |
[email protected] | 8c83a71c | 2013-12-16 18:02:58 | [diff] [blame] | 412 | void ClientSession::OnLocalMouseMoved(const webrtc::DesktopVector& position) { |
[email protected] | ec641187 | 2011-11-11 03:28:55 | [diff] [blame] | 413 | DCHECK(CalledOnValidThread()); |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 414 | remote_input_filter_.LocalMouseMoved(position); |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 415 | } |
[email protected] | ec641187 | 2011-11-11 03:28:55 | [diff] [blame] | 416 | |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 417 | void ClientSession::SetDisableInputs(bool disable_inputs) { |
| 418 | DCHECK(CalledOnValidThread()); |
| 419 | |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 420 | if (disable_inputs) |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 421 | input_tracker_.ReleaseAll(); |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 422 | |
| 423 | disable_input_filter_.set_enabled(!disable_inputs); |
| 424 | disable_clipboard_filter_.set_enabled(!disable_inputs); |
[email protected] | c78669c9 | 2011-06-13 22:42:38 | [diff] [blame] | 425 | } |
| 426 | |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame^] | 427 | std::unique_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() { |
[email protected] | 7f44ba4 | 2012-05-31 20:26:29 | [diff] [blame] | 428 | DCHECK(CalledOnValidThread()); |
| 429 | |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame^] | 430 | return base::WrapUnique( |
sergeyu | 2d69088 | 2014-10-01 02:36:43 | [diff] [blame] | 431 | new protocol::ClipboardThreadProxy(client_clipboard_factory_.GetWeakPtr(), |
anujk.sharma | bb80293 | 2015-05-05 21:57:29 | [diff] [blame] | 432 | base::ThreadTaskRunnerHandle::Get())); |
[email protected] | 7f44ba4 | 2012-05-31 20:26:29 | [diff] [blame] | 433 | } |
| 434 | |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 435 | void ClientSession::OnScreenSizeChanged(const webrtc::DesktopSize& size, |
| 436 | const webrtc::DesktopVector& dpi) { |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 437 | DCHECK(CalledOnValidThread()); |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 438 | |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 439 | mouse_clamping_filter_.set_input_size(size); |
| 440 | mouse_clamping_filter_.set_output_size(size); |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 441 | |
| 442 | if (connection_->session()->config().protocol() == |
| 443 | protocol::SessionConfig::Protocol::WEBRTC) { |
| 444 | protocol::VideoLayout layout; |
| 445 | protocol::VideoTrackLayout* video_track = layout.add_video_track(); |
| 446 | video_track->set_position_x(0); |
| 447 | video_track->set_position_y(0); |
| 448 | video_track->set_width(size.width() * kDefaultDpi / dpi.x()); |
| 449 | video_track->set_height(size.height() * kDefaultDpi / dpi.y()); |
| 450 | video_track->set_x_dpi(dpi.x()); |
| 451 | video_track->set_y_dpi(dpi.y()); |
| 452 | connection_->client_stub()->SetVideoLayout(layout); |
| 453 | } |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 454 | } |
| 455 | |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 456 | } // namespace remoting |