Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/host/client_session.h" | 5 #include "remoting/host/client_session.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/message_loop_proxy.h" | 9 #include "base/message_loop_proxy.h" |
| 10 #include "remoting/base/encoder.h" | |
| 11 #include "remoting/base/encoder_row_based.h" | |
| 12 #include "remoting/base/encoder_vp8.h" | |
| 13 #include "remoting/codec/audio_encoder.h" | |
| 14 #include "remoting/codec/audio_encoder_verbatim.h" | |
| 15 #include "remoting/host/audio_capturer.h" | |
| 16 #include "remoting/host/audio_scheduler.h" | |
| 17 #include "remoting/host/desktop_environment.h" | |
| 18 #include "remoting/host/event_executor.h" | |
| 19 #include "remoting/host/screen_recorder.h" | |
| 10 #include "remoting/host/video_frame_capturer.h" | 20 #include "remoting/host/video_frame_capturer.h" |
| 11 #include "remoting/proto/control.pb.h" | 21 #include "remoting/proto/control.pb.h" |
| 12 #include "remoting/proto/event.pb.h" | 22 #include "remoting/proto/event.pb.h" |
| 13 #include "remoting/protocol/client_stub.h" | 23 #include "remoting/protocol/client_stub.h" |
| 14 #include "remoting/protocol/clipboard_thread_proxy.h" | 24 #include "remoting/protocol/clipboard_thread_proxy.h" |
| 15 | 25 |
| 16 namespace remoting { | 26 namespace remoting { |
| 17 | 27 |
| 18 ClientSession::ClientSession( | 28 ClientSession::ClientSession( |
| 19 EventHandler* event_handler, | 29 EventHandler* event_handler, |
| 30 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, | |
| 31 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, | |
| 32 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, | |
| 20 scoped_ptr<protocol::ConnectionToClient> connection, | 33 scoped_ptr<protocol::ConnectionToClient> connection, |
| 21 protocol::ClipboardStub* host_clipboard_stub, | 34 scoped_ptr<DesktopEnvironment> desktop_environment, |
| 22 protocol::InputStub* host_input_stub, | |
| 23 VideoFrameCapturer* capturer, | |
| 24 const base::TimeDelta& max_duration) | 35 const base::TimeDelta& max_duration) |
| 25 : event_handler_(event_handler), | 36 : event_handler_(event_handler), |
| 26 connection_(connection.Pass()), | 37 connection_(connection.Pass()), |
| 38 desktop_environment_(desktop_environment.Pass()), | |
| 27 client_jid_(connection_->session()->jid()), | 39 client_jid_(connection_->session()->jid()), |
| 28 is_authenticated_(false), | 40 is_authenticated_(false), |
| 29 host_clipboard_stub_(host_clipboard_stub), | 41 host_clipboard_stub_(desktop_environment_->event_executor()), |
| 30 host_input_stub_(host_input_stub), | 42 host_input_stub_(desktop_environment_->event_executor()), |
| 31 input_tracker_(host_input_stub_), | 43 input_tracker_(host_input_stub_), |
| 32 remote_input_filter_(&input_tracker_), | 44 remote_input_filter_(&input_tracker_), |
| 33 mouse_input_filter_(&remote_input_filter_), | 45 mouse_input_filter_(&remote_input_filter_), |
| 34 client_clipboard_factory_(clipboard_echo_filter_.client_filter()), | 46 client_clipboard_factory_(clipboard_echo_filter_.client_filter()), |
| 35 capturer_(capturer), | 47 capturer_(desktop_environment_->video_capturer()), |
| 36 max_duration_(max_duration) { | 48 max_duration_(max_duration), |
| 49 capture_task_runner_(capture_task_runner), | |
| 50 encode_task_runner_(encode_task_runner), | |
| 51 network_task_runner_(network_task_runner), | |
| 52 active_recorders_(0) { | |
| 37 connection_->SetEventHandler(this); | 53 connection_->SetEventHandler(this); |
| 38 | 54 |
| 39 // TODO(sergeyu): Currently ConnectionToClient expects stubs to be | 55 // TODO(sergeyu): Currently ConnectionToClient expects stubs to be |
| 40 // set before channels are connected. Make it possible to set stubs | 56 // set before channels are connected. Make it possible to set stubs |
| 41 // later and set them only when connection is authenticated. | 57 // later and set them only when connection is authenticated. |
| 42 connection_->set_clipboard_stub(&auth_clipboard_filter_); | 58 connection_->set_clipboard_stub(&auth_clipboard_filter_); |
| 43 connection_->set_host_stub(this); | 59 connection_->set_host_stub(this); |
| 44 connection_->set_input_stub(this); | 60 connection_->set_input_stub(this); |
| 45 clipboard_echo_filter_.set_host_stub(host_clipboard_stub_); | 61 clipboard_echo_filter_.set_host_stub(host_clipboard_stub_); |
| 46 } | 62 } |
| 47 | 63 |
| 48 ClientSession::~ClientSession() { | 64 ClientSession::~ClientSession() { |
| 65 DCHECK(desktop_environment_.get() == NULL); | |
| 49 } | 66 } |
| 50 | 67 |
| 51 void ClientSession::InjectKeyEvent(const protocol::KeyEvent& event) { | 68 void ClientSession::InjectKeyEvent(const protocol::KeyEvent& event) { |
| 52 DCHECK(CalledOnValidThread()); | 69 DCHECK(CalledOnValidThread()); |
| 53 auth_input_filter_.InjectKeyEvent(event); | 70 auth_input_filter_.InjectKeyEvent(event); |
| 54 } | 71 } |
| 55 | 72 |
| 56 void ClientSession::InjectMouseEvent(const protocol::MouseEvent& event) { | 73 void ClientSession::InjectMouseEvent(const protocol::MouseEvent& event) { |
| 57 DCHECK(CalledOnValidThread()); | 74 DCHECK(CalledOnValidThread()); |
| 58 | 75 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 } | 117 } |
| 101 | 118 |
| 102 event_handler_->OnSessionAuthenticated(this); | 119 event_handler_->OnSessionAuthenticated(this); |
| 103 } | 120 } |
| 104 | 121 |
| 105 void ClientSession::OnConnectionChannelsConnected( | 122 void ClientSession::OnConnectionChannelsConnected( |
| 106 protocol::ConnectionToClient* connection) { | 123 protocol::ConnectionToClient* connection) { |
| 107 DCHECK(CalledOnValidThread()); | 124 DCHECK(CalledOnValidThread()); |
| 108 DCHECK_EQ(connection_.get(), connection); | 125 DCHECK_EQ(connection_.get(), connection); |
| 109 SetDisableInputs(false); | 126 SetDisableInputs(false); |
| 127 | |
| 128 // Then we create a ScreenRecorder passing the message loops that | |
|
Wez
2012/08/31 18:18:02
nit: Drop "Then we".
alexeypa (please no reviews)
2012/08/31 23:13:30
Done.
| |
| 129 // it should run on. | |
| 130 Encoder* encoder = CreateEncoder(connection_->session()->config()); | |
| 131 video_recorder_ = new ScreenRecorder( | |
| 132 capture_task_runner_, | |
| 133 encode_task_runner_, | |
| 134 network_task_runner_, | |
| 135 desktop_environment_->video_capturer(), | |
| 136 encoder); | |
| 137 ++active_recorders_; | |
| 138 | |
| 139 if (connection_->session()->config().is_audio_enabled()) { | |
| 140 scoped_ptr<AudioEncoder> audio_encoder = | |
| 141 CreateAudioEncoder(connection_->session()->config()); | |
| 142 audio_scheduler_ = new AudioScheduler( | |
| 143 capture_task_runner_, | |
| 144 network_task_runner_, | |
| 145 desktop_environment_->audio_capturer(), | |
| 146 audio_encoder.Pass(), | |
| 147 connection_->audio_stub()); | |
| 148 ++active_recorders_; | |
| 149 } | |
| 150 | |
| 151 // Immediately add the connection and start the session. | |
|
Wez
2012/08/31 18:18:02
nit: Suggest just "Start the session."
alexeypa (please no reviews)
2012/08/31 23:13:30
Done.
| |
| 152 video_recorder_->AddConnection(connection_.get()); | |
| 153 video_recorder_->Start(); | |
| 154 desktop_environment_->Start(CreateClipboardProxy()); | |
| 155 | |
| 110 event_handler_->OnSessionChannelsConnected(this); | 156 event_handler_->OnSessionChannelsConnected(this); |
| 111 } | 157 } |
| 112 | 158 |
| 113 void ClientSession::OnConnectionClosed( | 159 void ClientSession::OnConnectionClosed( |
| 114 protocol::ConnectionToClient* connection, | 160 protocol::ConnectionToClient* connection, |
| 115 protocol::ErrorCode error) { | 161 protocol::ErrorCode error) { |
| 116 DCHECK(CalledOnValidThread()); | 162 DCHECK(CalledOnValidThread()); |
| 117 DCHECK_EQ(connection_.get(), connection); | 163 DCHECK_EQ(connection_.get(), connection); |
| 118 if (!is_authenticated_) | 164 if (!is_authenticated_) |
| 119 event_handler_->OnSessionAuthenticationFailed(this); | 165 event_handler_->OnSessionAuthenticationFailed(this); |
| 120 auth_input_filter_.set_input_stub(NULL); | 166 auth_input_filter_.set_input_stub(NULL); |
| 121 auth_clipboard_filter_.set_clipboard_stub(NULL); | 167 auth_clipboard_filter_.set_clipboard_stub(NULL); |
| 122 | 168 |
| 123 // Ensure that any pressed keys or buttons are released. | 169 // Ensure that any pressed keys or buttons are released. |
| 124 input_tracker_.ReleaseAll(); | 170 input_tracker_.ReleaseAll(); |
| 125 | 171 |
| 126 // TODO(sergeyu): Log failure reason? | 172 // TODO(sergeyu): Log failure reason? |
| 127 event_handler_->OnSessionClosed(this); | 173 event_handler_->OnSessionClosed(this); |
| 128 } | 174 } |
| 129 | 175 |
| 130 void ClientSession::OnSequenceNumberUpdated( | 176 void ClientSession::OnSequenceNumberUpdated( |
| 131 protocol::ConnectionToClient* connection, int64 sequence_number) { | 177 protocol::ConnectionToClient* connection, int64 sequence_number) { |
| 132 DCHECK(CalledOnValidThread()); | 178 DCHECK(CalledOnValidThread()); |
| 133 DCHECK_EQ(connection_.get(), connection); | 179 DCHECK_EQ(connection_.get(), connection); |
| 180 | |
| 181 if (video_recorder_.get()) | |
| 182 video_recorder_->UpdateSequenceNumber(sequence_number); | |
| 183 | |
| 134 event_handler_->OnSessionSequenceNumber(this, sequence_number); | 184 event_handler_->OnSessionSequenceNumber(this, sequence_number); |
| 135 } | 185 } |
| 136 | 186 |
| 137 void ClientSession::OnRouteChange( | 187 void ClientSession::OnRouteChange( |
| 138 protocol::ConnectionToClient* connection, | 188 protocol::ConnectionToClient* connection, |
| 139 const std::string& channel_name, | 189 const std::string& channel_name, |
| 140 const protocol::TransportRoute& route) { | 190 const protocol::TransportRoute& route) { |
| 141 DCHECK(CalledOnValidThread()); | 191 DCHECK(CalledOnValidThread()); |
| 142 DCHECK_EQ(connection_.get(), connection); | 192 DCHECK_EQ(connection_.get(), connection); |
| 143 event_handler_->OnSessionRouteChange(this, channel_name, route); | 193 event_handler_->OnSessionRouteChange(this, channel_name, route); |
| 144 } | 194 } |
| 145 | 195 |
| 146 void ClientSession::Disconnect() { | 196 void ClientSession::Disconnect() { |
| 147 DCHECK(CalledOnValidThread()); | 197 DCHECK(CalledOnValidThread()); |
| 148 DCHECK(connection_.get()); | 198 DCHECK(connection_.get()); |
| 149 | 199 |
| 150 max_duration_timer_.Stop(); | 200 max_duration_timer_.Stop(); |
| 151 // This triggers OnConnectionClosed(), and the session may be destroyed | 201 // This triggers OnConnectionClosed(), and the session may be destroyed |
| 152 // as the result, so this call must be the last in this method. | 202 // as the result, so this call must be the last in this method. |
| 153 connection_->Disconnect(); | 203 connection_->Disconnect(); |
| 154 } | 204 } |
| 155 | 205 |
| 206 void ClientSession::StopAndDelete() { | |
| 207 DCHECK(CalledOnValidThread()); | |
| 208 | |
| 209 if (audio_scheduler_.get()) { | |
| 210 audio_scheduler_->OnClientDisconnected(); | |
| 211 StopAudioScheduler(); | |
| 212 } | |
| 213 | |
| 214 if (video_recorder_.get()) { | |
| 215 video_recorder_->RemoveConnection(connection_.get()); | |
| 216 StopScreenRecorder(); | |
| 217 } | |
| 218 | |
| 219 if (!active_recorders_) { | |
| 220 desktop_environment_.release()->StopAndDelete(); | |
| 221 delete this; | |
| 222 } | |
| 223 } | |
| 224 | |
| 156 void ClientSession::LocalMouseMoved(const SkIPoint& mouse_pos) { | 225 void ClientSession::LocalMouseMoved(const SkIPoint& mouse_pos) { |
| 157 DCHECK(CalledOnValidThread()); | 226 DCHECK(CalledOnValidThread()); |
| 158 remote_input_filter_.LocalMouseMoved(mouse_pos); | 227 remote_input_filter_.LocalMouseMoved(mouse_pos); |
| 159 } | 228 } |
| 160 | 229 |
| 161 void ClientSession::SetDisableInputs(bool disable_inputs) { | 230 void ClientSession::SetDisableInputs(bool disable_inputs) { |
| 162 DCHECK(CalledOnValidThread()); | 231 DCHECK(CalledOnValidThread()); |
| 163 | 232 |
| 164 if (disable_inputs) { | 233 if (disable_inputs) { |
| 165 disable_input_filter_.set_input_stub(NULL); | 234 disable_input_filter_.set_input_stub(NULL); |
| 166 disable_clipboard_filter_.set_clipboard_stub(NULL); | 235 disable_clipboard_filter_.set_clipboard_stub(NULL); |
| 167 input_tracker_.ReleaseAll(); | 236 input_tracker_.ReleaseAll(); |
| 168 } else { | 237 } else { |
| 169 disable_input_filter_.set_input_stub(&mouse_input_filter_); | 238 disable_input_filter_.set_input_stub(&mouse_input_filter_); |
| 170 disable_clipboard_filter_.set_clipboard_stub( | 239 disable_clipboard_filter_.set_clipboard_stub( |
| 171 clipboard_echo_filter_.host_filter()); | 240 clipboard_echo_filter_.host_filter()); |
| 172 } | 241 } |
| 173 } | 242 } |
| 174 | 243 |
| 175 scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() { | 244 scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() { |
| 176 DCHECK(CalledOnValidThread()); | 245 DCHECK(CalledOnValidThread()); |
| 177 | 246 |
| 178 return scoped_ptr<protocol::ClipboardStub>( | 247 return scoped_ptr<protocol::ClipboardStub>( |
| 179 new protocol::ClipboardThreadProxy( | 248 new protocol::ClipboardThreadProxy( |
| 180 client_clipboard_factory_.GetWeakPtr(), | 249 client_clipboard_factory_.GetWeakPtr(), |
| 181 base::MessageLoopProxy::current())); | 250 base::MessageLoopProxy::current())); |
| 182 } | 251 } |
| 183 | 252 |
| 253 // TODO(sergeyu): Move this to SessionManager? | |
| 254 // static | |
| 255 Encoder* ClientSession::CreateEncoder(const protocol::SessionConfig& config) { | |
| 256 const protocol::ChannelConfig& video_config = config.video_config(); | |
| 257 | |
| 258 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { | |
| 259 return EncoderRowBased::CreateVerbatimEncoder(); | |
| 260 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) { | |
| 261 return EncoderRowBased::CreateZlibEncoder(); | |
| 262 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) { | |
| 263 return new remoting::EncoderVp8(); | |
| 264 } | |
| 265 | |
| 266 return NULL; | |
| 267 } | |
| 268 | |
| 269 // static | |
| 270 scoped_ptr<AudioEncoder> ClientSession::CreateAudioEncoder( | |
| 271 const protocol::SessionConfig& config) { | |
| 272 const protocol::ChannelConfig& audio_config = config.audio_config(); | |
| 273 | |
| 274 if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { | |
| 275 return scoped_ptr<AudioEncoder>(new AudioEncoderVerbatim()); | |
| 276 } | |
| 277 | |
| 278 NOTIMPLEMENTED(); | |
| 279 return scoped_ptr<AudioEncoder>(NULL); | |
| 280 } | |
| 281 | |
| 282 void ClientSession::OnRecorderStopped() { | |
| 283 if (!network_task_runner_->BelongsToCurrentThread()) { | |
| 284 network_task_runner_->PostTask( | |
| 285 FROM_HERE, base::Bind(&ClientSession::OnRecorderStopped, | |
| 286 base::Unretained(this))); | |
| 287 return; | |
| 288 } | |
| 289 | |
| 290 --active_recorders_; | |
| 291 DCHECK_GE(active_recorders_, 0); | |
| 292 | |
| 293 StopAndDelete(); | |
| 294 } | |
| 295 | |
| 296 void ClientSession::StopAudioScheduler() { | |
| 297 DCHECK(CalledOnValidThread()); | |
| 298 DCHECK(audio_scheduler_.get()); | |
| 299 | |
| 300 scoped_refptr<AudioScheduler> audio_scheduler = audio_scheduler_; | |
| 301 audio_scheduler_ = NULL; | |
| 302 audio_scheduler->Stop(base::Bind(&ClientSession::OnRecorderStopped, | |
| 303 base::Unretained(this))); | |
| 304 } | |
| 305 | |
| 306 void ClientSession::StopScreenRecorder() { | |
| 307 DCHECK(CalledOnValidThread()); | |
| 308 DCHECK(video_recorder_.get()); | |
| 309 | |
| 310 scoped_refptr<ScreenRecorder> video_recorder = video_recorder_; | |
| 311 video_recorder_ = NULL; | |
| 312 video_recorder->Stop(base::Bind(&ClientSession::OnRecorderStopped, | |
| 313 base::Unretained(this))); | |
| 314 } | |
| 315 | |
| 184 } // namespace remoting | 316 } // namespace remoting |
| OLD | NEW |