[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" |
gab | bac02f5 | 2016-05-11 17:55:51 | [diff] [blame] | 13 | #include "base/threading/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] | ce404ca | 2013-01-16 17:23:53 | [diff] [blame] | 18 | #include "remoting/host/audio_capturer.h" |
[email protected] | 170cba4 | 2012-09-12 22:28:39 | [diff] [blame] | 19 | #include "remoting/host/desktop_environment.h" |
[email protected] | 399b4f6 | 2014-05-30 20:13:15 | [diff] [blame] | 20 | #include "remoting/host/host_extension_session.h" |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 21 | #include "remoting/host/input_injector.h" |
sergeyu | 1afb35a1 | 2015-02-13 18:45:30 | [diff] [blame] | 22 | #include "remoting/host/mouse_shape_pump.h" |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 23 | #include "remoting/host/screen_controls.h" |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 24 | #include "remoting/host/screen_resolution.h" |
[email protected] | 50d71c7 | 2012-05-03 01:28:55 | [diff] [blame] | 25 | #include "remoting/proto/control.pb.h" |
[email protected] | c78669c9 | 2011-06-13 22:42:38 | [diff] [blame] | 26 | #include "remoting/proto/event.pb.h" |
sergeyu | cd16e206 | 2016-09-12 19:28:35 | [diff] [blame] | 27 | #include "remoting/protocol/audio_stream.h" |
[email protected] | ff3761a1 | 2012-05-22 22:29:24 | [diff] [blame] | 28 | #include "remoting/protocol/client_stub.h" |
[email protected] | 7f44ba4 | 2012-05-31 20:26:29 | [diff] [blame] | 29 | #include "remoting/protocol/clipboard_thread_proxy.h" |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 30 | #include "remoting/protocol/pairing_registry.h" |
sergeyu | b031cd2 | 2015-11-19 22:17:13 | [diff] [blame] | 31 | #include "remoting/protocol/session.h" |
| 32 | #include "remoting/protocol/session_config.h" |
sergeyu | 4d20800 | 2015-11-23 22:27:43 | [diff] [blame] | 33 | #include "remoting/protocol/video_frame_pump.h" |
[email protected] | 4e719f4 | 2014-08-12 18:04:37 | [diff] [blame] | 34 | #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" |
[email protected] | c78669c9 | 2011-06-13 22:42:38 | [diff] [blame] | 35 | |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 36 | namespace remoting { |
[email protected] | 48a8ca3 | 2013-02-13 04:31:01 | [diff] [blame] | 37 | |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 38 | namespace { |
| 39 | |
wez | 6e95a37 | 2015-07-08 22:33:31 | [diff] [blame] | 40 | // Name of command-line flag to disable use of I444 by default. |
| 41 | const char kDisableI444SwitchName[] = "disable-i444"; |
wez | 43ac266 | 2015-06-10 18:22:29 | [diff] [blame] | 42 | |
sergeyu | 7bc8760 | 2015-02-13 20:33:28 | [diff] [blame] | 43 | } // namespace |
| 44 | |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 45 | ClientSession::ClientSession( |
| 46 | EventHandler* event_handler, |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame] | 47 | std::unique_ptr<protocol::ConnectionToClient> connection, |
[email protected] | 8190479 | 2012-10-18 04:16:28 | [diff] [blame] | 48 | DesktopEnvironmentFactory* desktop_environment_factory, |
zijiehe | 4aa6ea4 | 2016-11-12 01:28:16 | [diff] [blame] | 49 | const DesktopEnvironmentOptions& desktop_environment_options, |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 50 | const base::TimeDelta& max_duration, |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 51 | scoped_refptr<protocol::PairingRegistry> pairing_registry, |
| 52 | const std::vector<HostExtension*>& extensions) |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 53 | : event_handler_(event_handler), |
sergeyu | 1417e013 | 2015-12-23 19:01:22 | [diff] [blame] | 54 | connection_(std::move(connection)), |
[email protected] | 3361e1f | 2012-03-20 20:31:44 | [diff] [blame] | 55 | client_jid_(connection_->session()->jid()), |
[email protected] | 233bb94 | 2013-03-15 07:18:17 | [diff] [blame] | 56 | desktop_environment_factory_(desktop_environment_factory), |
zijiehe | 4aa6ea4 | 2016-11-12 01:28:16 | [diff] [blame] | 57 | desktop_environment_options_(desktop_environment_options), |
[email protected] | eccc2d4 | 2013-01-10 19:35:14 | [diff] [blame] | 58 | input_tracker_(&host_input_filter_), |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 59 | remote_input_filter_(&input_tracker_), |
[email protected] | 58f1ad4 | 2013-01-10 23:49:51 | [diff] [blame] | 60 | mouse_clamping_filter_(&remote_input_filter_), |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 61 | disable_input_filter_(&mouse_clamping_filter_), |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 62 | disable_clipboard_filter_(clipboard_echo_filter_.host_filter()), |
[email protected] | 7f44ba4 | 2012-05-31 20:26:29 | [diff] [blame] | 63 | client_clipboard_factory_(clipboard_echo_filter_.client_filter()), |
[email protected] | 170cba4 | 2012-09-12 22:28:39 | [diff] [blame] | 64 | max_duration_(max_duration), |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 65 | pairing_registry_(pairing_registry), |
wez | 6e95a37 | 2015-07-08 22:33:31 | [diff] [blame] | 66 | // 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.a | 933aeaf | 2014-09-20 13:19:17 | [diff] [blame] | 70 | weak_factory_(this) { |
zijiehe | f38c972 | 2017-02-08 02:05:29 | [diff] [blame] | 71 | connection_->session()->AddPlugin(&host_experiment_session_plugin_); |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 72 | connection_->SetEventHandler(this); |
| 73 | |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 74 | // Create a manager for the configured extensions, if any. |
| 75 | extension_manager_.reset(new HostExtensionSessionManager(extensions, this)); |
| 76 | |
[email protected] | 2f408489 | 2013-02-25 20:30:20 | [diff] [blame] | 77 | #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] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 82 | } |
| 83 | |
[email protected] | f19f09ca | 2013-03-13 11:10:29 | [diff] [blame] | 84 | ClientSession::~ClientSession() { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 85 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
sergeyu | cd16e206 | 2016-09-12 19:28:35 | [diff] [blame] | 86 | DCHECK(!audio_stream_); |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 87 | DCHECK(!desktop_environment_); |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 88 | DCHECK(!input_injector_); |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 89 | DCHECK(!screen_controls_); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 90 | DCHECK(!video_stream_); |
[email protected] | f19f09ca | 2013-03-13 11:10:29 | [diff] [blame] | 91 | |
| 92 | connection_.reset(); |
| 93 | } |
| 94 | |
[email protected] | 48a8ca3 | 2013-02-13 04:31:01 | [diff] [blame] | 95 | void ClientSession::NotifyClientResolution( |
| 96 | const protocol::ClientResolution& resolution) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 97 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
sergeyu | 54624e1 | 2016-06-01 10:54:31 | [diff] [blame] | 98 | DCHECK(resolution.dips_width() > 0 && resolution.dips_height() > 0); |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 99 | |
| 100 | VLOG(1) << "Received ClientResolution (dips_width=" |
| 101 | << resolution.dips_width() << ", dips_height=" |
| 102 | << resolution.dips_height() << ")"; |
| 103 | |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 104 | if (!screen_controls_) |
[email protected] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 105 | return; |
| 106 | |
sergeyu | f00bde3 | 2016-08-09 22:10:02 | [diff] [blame] | 107 | 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] | 739e280 | 2013-03-18 01:03:48 | [diff] [blame] | 119 | |
| 120 | // Try to match the client's resolution. |
sergeyu | f00bde3 | 2016-08-09 22:10:02 | [diff] [blame] | 121 | // TODO(sergeyu): Pass clients DPI to the resizer. |
| 122 | screen_controls_->SetScreenResolution(ScreenResolution( |
| 123 | client_size, webrtc::DesktopVector(kDefaultDpi, kDefaultDpi))); |
[email protected] | 50d71c7 | 2012-05-03 01:28:55 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | void ClientSession::ControlVideo(const protocol::VideoControl& video_control) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 127 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 128 | |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 129 | // Note that |video_stream_| may be null, depending upon whether |
sergeyu | 10ce97b | 2015-02-05 23:53:14 | [diff] [blame] | 130 | // extensions choose to wrap or "steal" the video capturer or encoder. |
[email protected] | 50d71c7 | 2012-05-03 01:28:55 | [diff] [blame] | 131 | if (video_control.has_enable()) { |
| 132 | VLOG(1) << "Received VideoControl (enable=" |
| 133 | << video_control.enable() << ")"; |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 134 | pause_video_ = !video_control.enable(); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 135 | if (video_stream_) |
| 136 | video_stream_->Pause(pause_video_); |
[email protected] | 50d71c7 | 2012-05-03 01:28:55 | [diff] [blame] | 137 | } |
[email protected] | a516f1e | 2014-05-30 07:21:20 | [diff] [blame] | 138 | if (video_control.has_lossless_encode()) { |
| 139 | VLOG(1) << "Received VideoControl (lossless_encode=" |
| 140 | << video_control.lossless_encode() << ")"; |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 141 | lossless_video_encode_ = video_control.lossless_encode(); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 142 | if (video_stream_) |
| 143 | video_stream_->SetLosslessEncode(lossless_video_encode_); |
[email protected] | a516f1e | 2014-05-30 07:21:20 | [diff] [blame] | 144 | } |
| 145 | if (video_control.has_lossless_color()) { |
| 146 | VLOG(1) << "Received VideoControl (lossless_color=" |
| 147 | << video_control.lossless_color() << ")"; |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 148 | lossless_video_color_ = video_control.lossless_color(); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 149 | if (video_stream_) |
| 150 | video_stream_->SetLosslessColor(lossless_video_color_); |
[email protected] | a516f1e | 2014-05-30 07:21:20 | [diff] [blame] | 151 | } |
[email protected] | f2b9cf3 | 2012-04-27 00:13:43 | [diff] [blame] | 152 | } |
| 153 | |
[email protected] | f458bed | 2012-10-18 03:27:59 | [diff] [blame] | 154 | void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 155 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 156 | |
[email protected] | f458bed | 2012-10-18 03:27:59 | [diff] [blame] | 157 | if (audio_control.has_enable()) { |
| 158 | VLOG(1) << "Received AudioControl (enable=" |
| 159 | << audio_control.enable() << ")"; |
sergeyu | cd16e206 | 2016-09-12 19:28:35 | [diff] [blame] | 160 | if (audio_stream_) |
| 161 | audio_stream_->Pause(!audio_control.enable()); |
[email protected] | f458bed | 2012-10-18 03:27:59 | [diff] [blame] | 162 | } |
| 163 | } |
| 164 | |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 165 | void ClientSession::SetCapabilities( |
| 166 | const protocol::Capabilities& capabilities) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 167 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 168 | |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 169 | // 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] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 175 | // Compute the set of capabilities supported by both client and host. |
ricea | 68860bd | 2016-08-22 02:48:56 | [diff] [blame] | 176 | client_capabilities_ = base::MakeUnique<std::string>(); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 177 | if (capabilities.has_capabilities()) |
| 178 | *client_capabilities_ = capabilities.capabilities(); |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 179 | capabilities_ = IntersectCapabilities(*client_capabilities_, |
| 180 | host_capabilities_); |
| 181 | extension_manager_->OnNegotiatedCapabilities( |
| 182 | connection_->client_stub(), capabilities_); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 183 | |
| 184 | VLOG(1) << "Client capabilities: " << *client_capabilities_; |
| 185 | |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 186 | desktop_environment_->SetCapabilities(capabilities_); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 187 | } |
| 188 | |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 189 | void ClientSession::RequestPairing( |
| 190 | const protocol::PairingRequest& pairing_request) { |
dcheng | ac10e4a8 | 2014-08-26 03:53:44 | [diff] [blame] | 191 | if (pairing_registry_.get() && pairing_request.has_client_name()) { |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 192 | protocol::PairingRegistry::Pairing pairing = |
| 193 | pairing_registry_->CreatePairing(pairing_request.client_name()); |
| 194 | protocol::PairingResponse pairing_response; |
[email protected] | df5189f | 2013-06-18 12:12:05 | [diff] [blame] | 195 | pairing_response.set_client_id(pairing.client_id()); |
| 196 | pairing_response.set_shared_secret(pairing.shared_secret()); |
[email protected] | 8835692 | 2013-06-04 06:26:01 | [diff] [blame] | 197 | connection_->client_stub()->SetPairingResponse(pairing_response); |
| 198 | } |
| 199 | } |
| 200 | |
[email protected] | 09eabd65c | 2013-08-13 00:13:48 | [diff] [blame] | 201 | void ClientSession::DeliverClientMessage( |
| 202 | const protocol::ExtensionMessage& message) { |
[email protected] | af278c4 | 2013-09-02 05:27:00 | [diff] [blame] | 203 | 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] | 399b4f6 | 2014-05-30 20:13:15 | [diff] [blame] | 211 | } else { |
wez | 73f19de | 2014-10-29 19:06:33 | [diff] [blame] | 212 | if (extension_manager_->OnExtensionMessage(message)) |
wez | 8703699 | 2014-09-05 00:53:43 | [diff] [blame] | 213 | return; |
| 214 | |
| 215 | DLOG(INFO) << "Unexpected message received: " |
| 216 | << message.type() << ": " << message.data(); |
[email protected] | af278c4 | 2013-09-02 05:27:00 | [diff] [blame] | 217 | } |
| 218 | } |
[email protected] | 09eabd65c | 2013-08-13 00:13:48 | [diff] [blame] | 219 | } |
| 220 | |
sergeyu | 4e1f4cd | 2016-09-27 00:42:52 | [diff] [blame] | 221 | void ClientSession::OnConnectionAuthenticating() { |
[email protected] | 064128c | 2014-04-07 22:33:28 | [diff] [blame] | 222 | event_handler_->OnSessionAuthenticating(this); |
| 223 | } |
| 224 | |
sergeyu | 4e1f4cd | 2016-09-27 00:42:52 | [diff] [blame] | 225 | void ClientSession::OnConnectionAuthenticated() { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 226 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
sergeyu | cd16e206 | 2016-09-12 19:28:35 | [diff] [blame] | 227 | DCHECK(!audio_stream_); |
[email protected] | a5d181f | 2013-04-19 14:55:37 | [diff] [blame] | 228 | DCHECK(!desktop_environment_); |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 229 | DCHECK(!input_injector_); |
| 230 | DCHECK(!screen_controls_); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 231 | DCHECK(!video_stream_); |
[email protected] | 34df2ab | 2012-08-19 06:54:23 | [diff] [blame] | 232 | |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 233 | is_authenticated_ = true; |
[email protected] | 34df2ab | 2012-08-19 06:54:23 | [diff] [blame] | 234 | |
[email protected] | 5dc5b12a | 2012-06-23 01:05:14 | [diff] [blame] | 235 | if (max_duration_ > base::TimeDelta()) { |
sergeyu | ec77d854 | 2015-11-03 22:31:00 | [diff] [blame] | 236 | max_duration_timer_.Start( |
| 237 | FROM_HERE, max_duration_, |
| 238 | base::Bind(&ClientSession::DisconnectSession, base::Unretained(this), |
| 239 | protocol::MAX_SESSION_LENGTH)); |
[email protected] | 5dc5b12a | 2012-06-23 01:05:14 | [diff] [blame] | 240 | } |
[email protected] | 34df2ab | 2012-08-19 06:54:23 | [diff] [blame] | 241 | |
sergeyu | 21c899e | 2015-11-24 16:39:55 | [diff] [blame] | 242 | // Notify EventHandler. |
| 243 | event_handler_->OnSessionAuthenticated(this); |
[email protected] | ce404ca | 2013-01-16 17:23:53 | [diff] [blame] | 244 | |
zijiehe | f38c972 | 2017-02-08 02:05:29 | [diff] [blame] | 245 | DesktopEnvironmentOptions options = desktop_environment_options_; |
| 246 | options.ApplyHostSessionOptions(HostSessionOptions( |
| 247 | host_experiment_session_plugin_.configuration())); |
[email protected] | 96361d0 | 2013-05-08 18:26:18 | [diff] [blame] | 248 | // Create the desktop environment. Drop the connection if it could not be |
| 249 | // created for any reason (for instance the curtain could not initialize). |
zijiehe | f38c972 | 2017-02-08 02:05:29 | [diff] [blame] | 250 | desktop_environment_ = |
| 251 | desktop_environment_factory_->Create(weak_factory_.GetWeakPtr(), options); |
[email protected] | 96361d0 | 2013-05-08 18:26:18 | [diff] [blame] | 252 | if (!desktop_environment_) { |
sergeyu | ec77d854 | 2015-11-03 22:31:00 | [diff] [blame] | 253 | DisconnectSession(protocol::HOST_CONFIGURATION_ERROR); |
[email protected] | 96361d0 | 2013-05-08 18:26:18 | [diff] [blame] | 254 | return; |
| 255 | } |
| 256 | |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 257 | // Connect host stub. |
| 258 | connection_->set_host_stub(this); |
| 259 | |
[email protected] | 1b478ba | 2014-07-31 12:51:43 | [diff] [blame] | 260 | // Collate the set of capabilities to offer the client, if it supports them. |
sergeyu | f69b019f | 2014-09-13 20:41:02 | [diff] [blame] | 261 | host_capabilities_ = desktop_environment_->GetCapabilities(); |
| 262 | if (!host_capabilities_.empty()) |
| 263 | host_capabilities_.append(" "); |
| 264 | host_capabilities_.append(extension_manager_->GetCapabilities()); |
[email protected] | 233bb94 | 2013-03-15 07:18:17 | [diff] [blame] | 265 | |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 266 | // Create the object that controls the screen resolution. |
| 267 | screen_controls_ = desktop_environment_->CreateScreenControls(); |
[email protected] | 61cfdc5 | 2013-03-09 03:04:56 | [diff] [blame] | 268 | |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 269 | // Create the event executor. |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 270 | input_injector_ = desktop_environment_->CreateInputInjector(); |
[email protected] | eccc2d4 | 2013-01-10 19:35:14 | [diff] [blame] | 271 | |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 272 | // Connect the host input stubs. |
| 273 | connection_->set_input_stub(&disable_input_filter_); |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 274 | host_input_filter_.set_input_stub(input_injector_.get()); |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 275 | |
| 276 | // Connect the clipboard stubs. |
| 277 | connection_->set_clipboard_stub(&disable_clipboard_filter_); |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 278 | clipboard_echo_filter_.set_host_stub(input_injector_.get()); |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 279 | clipboard_echo_filter_.set_client_stub(connection_->client_stub()); |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 280 | } |
| 281 | |
sergeyu | 4e1f4cd | 2016-09-27 00:42:52 | [diff] [blame] | 282 | void ClientSession::CreateMediaStreams() { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 283 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
sergeyu | 9102cff | 2016-04-07 19:14:01 | [diff] [blame] | 284 | |
| 285 | // Create a VideoStream to pump frames from the capturer to the client. |
| 286 | video_stream_ = connection_->StartVideoStream( |
| 287 | desktop_environment_->CreateVideoCapturer()); |
| 288 | |
sergeyu | cd16e206 | 2016-09-12 19:28:35 | [diff] [blame] | 289 | // Create a AudioStream to pump audio from the capturer to the client. |
sergeyu | efb565c | 2016-10-11 15:29:01 | [diff] [blame] | 290 | 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 | } |
sergeyu | cd16e206 | 2016-09-12 19:28:35 | [diff] [blame] | 295 | |
sergeyu | ad51be8 | 2016-06-22 06:04:39 | [diff] [blame] | 296 | video_stream_->SetObserver(this); |
sergeyu | 9102cff | 2016-04-07 19:14:01 | [diff] [blame] | 297 | |
| 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_); |
sergeyu | b047307a | 2016-10-18 17:19:29 | [diff] [blame] | 304 | |
| 305 | if (event_timestamp_source_for_tests_) |
| 306 | video_stream_->SetEventTimestampsSource(event_timestamp_source_for_tests_); |
sergeyu | 9102cff | 2016-04-07 19:14:01 | [diff] [blame] | 307 | } |
| 308 | |
sergeyu | 4e1f4cd | 2016-09-27 00:42:52 | [diff] [blame] | 309 | void ClientSession::OnConnectionChannelsConnected() { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 310 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 311 | |
sergeyu | 9102cff | 2016-04-07 19:14:01 | [diff] [blame] | 312 | DCHECK(!channels_connected_); |
| 313 | channels_connected_ = true; |
| 314 | |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 315 | // Negotiate capabilities with the client. |
sergeyu | f69b019f | 2014-09-13 20:41:02 | [diff] [blame] | 316 | VLOG(1) << "Host capabilities: " << host_capabilities_; |
sergeyu | f69b019f | 2014-09-13 20:41:02 | [diff] [blame] | 317 | protocol::Capabilities capabilities; |
| 318 | capabilities.set_capabilities(host_capabilities_); |
| 319 | connection_->client_stub()->SetCapabilities(capabilities); |
[email protected] | 324b196 | 2013-05-01 19:30:22 | [diff] [blame] | 320 | |
| 321 | // Start the event executor. |
| 322 | input_injector_->Start(CreateClipboardProxy()); |
| 323 | SetDisableInputs(false); |
| 324 | |
sergeyu | 6ad12dc | 2016-04-02 00:01:32 | [diff] [blame] | 325 | // Create MouseShapePump to send mouse cursor shape. |
| 326 | mouse_shape_pump_.reset( |
| 327 | new MouseShapePump(desktop_environment_->CreateMouseCursorMonitor(), |
| 328 | connection_->client_stub())); |
| 329 | |
sergeyu | 9102cff | 2016-04-07 19:14:01 | [diff] [blame] | 330 | if (pending_video_layout_message_) { |
| 331 | connection_->client_stub()->SetVideoLayout(*pending_video_layout_message_); |
| 332 | pending_video_layout_message_.reset(); |
| 333 | } |
| 334 | |
[email protected] | cdd1c9e | 2012-10-26 21:14:04 | [diff] [blame] | 335 | // Notify the event handler that all our channels are now connected. |
[email protected] | cba6f81 | 2012-03-27 01:01:50 | [diff] [blame] | 336 | event_handler_->OnSessionChannelsConnected(this); |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 337 | } |
| 338 | |
sergeyu | 4e1f4cd | 2016-09-27 00:42:52 | [diff] [blame] | 339 | void ClientSession::OnConnectionClosed(protocol::ErrorCode error) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 340 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 341 | |
lukasza | f34d841 | 2015-04-30 23:09:59 | [diff] [blame] | 342 | HOST_LOG << "Client disconnected: " << client_jid_ << "; error = " << error; |
| 343 | |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 344 | // Ignore any further callbacks. |
kulkarni.a | 933aeaf | 2014-09-20 13:19:17 | [diff] [blame] | 345 | weak_factory_.InvalidateWeakPtrs(); |
[email protected] | a031c97 | 2012-12-27 20:10:40 | [diff] [blame] | 346 | |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 347 | // If the client never authenticated then the session failed. |
sergeyu | 1f8cd50 | 2015-02-13 21:45:53 | [diff] [blame] | 348 | if (!is_authenticated_) |
[email protected] | 1f249e2 | 2011-11-29 20:19:59 | [diff] [blame] | 349 | event_handler_->OnSessionAuthenticationFailed(this); |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 350 | |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 351 | // Ensure that any pressed keys or buttons are released. |
| 352 | input_tracker_.ReleaseAll(); |
| 353 | |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 354 | // Stop components access the client, audio or video stubs, which are no |
| 355 | // longer valid once ConnectionToClient calls OnConnectionClosed(). |
sergeyu | cd16e206 | 2016-09-12 19:28:35 | [diff] [blame] | 356 | audio_stream_.reset(); |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 357 | video_stream_.reset(); |
sergeyu | 1afb35a1 | 2015-02-13 18:45:30 | [diff] [blame] | 358 | mouse_shape_pump_.reset(); |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 359 | client_clipboard_factory_.InvalidateWeakPtrs(); |
[email protected] | b0b72f11 | 2013-03-24 03:42:42 | [diff] [blame] | 360 | input_injector_.reset(); |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 361 | screen_controls_.reset(); |
| 362 | desktop_environment_.reset(); |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 363 | |
| 364 | // Notify the ChromotingHost that this client is disconnected. |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 365 | event_handler_->OnSessionClosed(this); |
[email protected] | ee910fd | 2011-11-10 18:23:31 | [diff] [blame] | 366 | } |
| 367 | |
[email protected] | 17af2ab | 2012-02-02 04:07:52 | [diff] [blame] | 368 | void ClientSession::OnRouteChange( |
[email protected] | 17af2ab | 2012-02-02 04:07:52 | [diff] [blame] | 369 | const std::string& channel_name, |
[email protected] | be451c8 | 2012-03-20 22:24:47 | [diff] [blame] | 370 | const protocol::TransportRoute& route) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 371 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | be451c8 | 2012-03-20 22:24:47 | [diff] [blame] | 372 | event_handler_->OnSessionRouteChange(this, channel_name, route); |
[email protected] | 91e4b7f6 | 2012-01-25 23:23:02 | [diff] [blame] | 373 | } |
| 374 | |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 375 | const std::string& ClientSession::client_jid() const { |
| 376 | return client_jid_; |
| 377 | } |
| 378 | |
sergeyu | ec77d854 | 2015-11-03 22:31:00 | [diff] [blame] | 379 | void ClientSession::DisconnectSession(protocol::ErrorCode error) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 380 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | ec641187 | 2011-11-11 03:28:55 | [diff] [blame] | 381 | DCHECK(connection_.get()); |
[email protected] | a46bcef | 2011-11-11 01:27:23 | [diff] [blame] | 382 | |
[email protected] | 5dc5b12a | 2012-06-23 01:05:14 | [diff] [blame] | 383 | max_duration_timer_.Stop(); |
[email protected] | 24a2a9d2 | 2012-12-07 09:06:47 | [diff] [blame] | 384 | |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 385 | // This triggers OnConnectionClosed(), and the session may be destroyed |
[email protected] | a46bcef | 2011-11-11 01:27:23 | [diff] [blame] | 386 | // as the result, so this call must be the last in this method. |
sergeyu | ec77d854 | 2015-11-03 22:31:00 | [diff] [blame] | 387 | connection_->Disconnect(error); |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 388 | } |
| 389 | |
[email protected] | 8c83a71c | 2013-12-16 18:02:58 | [diff] [blame] | 390 | void ClientSession::OnLocalMouseMoved(const webrtc::DesktopVector& position) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 391 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 231316a | 2013-03-25 06:01:12 | [diff] [blame] | 392 | remote_input_filter_.LocalMouseMoved(position); |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 393 | } |
[email protected] | ec641187 | 2011-11-11 03:28:55 | [diff] [blame] | 394 | |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 395 | void ClientSession::SetDisableInputs(bool disable_inputs) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 396 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 397 | |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 398 | if (disable_inputs) |
[email protected] | 86cbe6b | 2012-04-03 00:56:18 | [diff] [blame] | 399 | input_tracker_.ReleaseAll(); |
[email protected] | 750ae6b | 2012-08-20 22:52:40 | [diff] [blame] | 400 | |
| 401 | disable_input_filter_.set_enabled(!disable_inputs); |
| 402 | disable_clipboard_filter_.set_enabled(!disable_inputs); |
[email protected] | c78669c9 | 2011-06-13 22:42:38 | [diff] [blame] | 403 | } |
| 404 | |
joedow | 4fa09d9 | 2016-06-27 21:26:17 | [diff] [blame] | 405 | uint32_t ClientSession::desktop_session_id() const { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 406 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
joedow | 4fa09d9 | 2016-06-27 21:26:17 | [diff] [blame] | 407 | DCHECK(desktop_environment_); |
| 408 | return desktop_environment_->GetDesktopSessionId(); |
| 409 | } |
| 410 | |
| 411 | ClientSessionControl* ClientSession::session_control() { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 412 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
joedow | 4fa09d9 | 2016-06-27 21:26:17 | [diff] [blame] | 413 | return this; |
| 414 | } |
| 415 | |
sergeyu | b047307a | 2016-10-18 17:19:29 | [diff] [blame] | 416 | void ClientSession::SetEventTimestampsSourceForTests( |
| 417 | scoped_refptr<protocol::InputEventTimestampsSource> |
| 418 | event_timestamp_source) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 419 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
sergeyu | b047307a | 2016-10-18 17:19:29 | [diff] [blame] | 420 | event_timestamp_source_for_tests_ = event_timestamp_source; |
| 421 | if (video_stream_) |
| 422 | video_stream_->SetEventTimestampsSource(event_timestamp_source_for_tests_); |
| 423 | } |
| 424 | |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame] | 425 | std::unique_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 426 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
ricea | 68860bd | 2016-08-22 02:48:56 | [diff] [blame] | 427 | return base::MakeUnique<protocol::ClipboardThreadProxy>( |
| 428 | client_clipboard_factory_.GetWeakPtr(), |
| 429 | base::ThreadTaskRunnerHandle::Get()); |
[email protected] | 7f44ba4 | 2012-05-31 20:26:29 | [diff] [blame] | 430 | } |
| 431 | |
sergeyu | ad51be8 | 2016-06-22 06:04:39 | [diff] [blame] | 432 | void ClientSession::OnVideoSizeChanged(protocol::VideoStream* video_stream, |
| 433 | const webrtc::DesktopSize& size, |
| 434 | const webrtc::DesktopVector& dpi) { |
gab | bf77513a | 2017-06-01 14:35:34 | [diff] [blame] | 435 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 436 | |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 437 | mouse_clamping_filter_.set_output_size(size); |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 438 | |
sergeyu | f8170a39 | 2016-04-08 22:12:19 | [diff] [blame] | 439 | switch (connection_->session()->config().protocol()) { |
| 440 | case protocol::SessionConfig::Protocol::ICE: |
| 441 | mouse_clamping_filter_.set_input_size(size); |
| 442 | break; |
sergeyu | 9102cff | 2016-04-07 19:14:01 | [diff] [blame] | 443 | |
sergeyu | f8170a39 | 2016-04-08 22:12:19 | [diff] [blame] | 444 | 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; |
sergeyu | 9102cff | 2016-04-07 19:14:01 | [diff] [blame] | 471 | } |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 472 | } |
sergeyu | a609b7a | 2015-11-30 06:25:39 | [diff] [blame] | 473 | } |
| 474 | |
[email protected] | 44f6076 | 2011-03-23 12:13:35 | [diff] [blame] | 475 | } // namespace remoting |