Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: remoting/host/client_session.cc

Issue 10915206: [Chromoting] Refactoring DesktopEnvironment and moving screen/audio recorders to ClientSession. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased to enable try jobs. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/codec/audio_encoder.h"
11 #include "remoting/codec/audio_encoder_speex.h"
12 #include "remoting/codec/audio_encoder_verbatim.h"
13 #include "remoting/codec/video_encoder.h"
14 #include "remoting/codec/video_encoder_row_based.h"
15 #include "remoting/codec/video_encoder_vp8.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 host_clipboard_stub_(host_clipboard_stub), 40 host_clipboard_stub_(desktop_environment_->event_executor()),
29 host_input_stub_(host_input_stub), 41 host_input_stub_(desktop_environment_->event_executor()),
30 input_tracker_(host_input_stub_), 42 input_tracker_(host_input_stub_),
31 remote_input_filter_(&input_tracker_), 43 remote_input_filter_(&input_tracker_),
32 mouse_clamping_filter_(capturer, &remote_input_filter_), 44 mouse_clamping_filter_(desktop_environment_->video_capturer(),
45 &remote_input_filter_),
33 disable_input_filter_(&mouse_clamping_filter_), 46 disable_input_filter_(&mouse_clamping_filter_),
34 disable_clipboard_filter_(clipboard_echo_filter_.host_filter()), 47 disable_clipboard_filter_(clipboard_echo_filter_.host_filter()),
35 auth_input_filter_(&disable_input_filter_), 48 auth_input_filter_(&disable_input_filter_),
36 auth_clipboard_filter_(&disable_clipboard_filter_), 49 auth_clipboard_filter_(&disable_clipboard_filter_),
37 client_clipboard_factory_(clipboard_echo_filter_.client_filter()), 50 client_clipboard_factory_(clipboard_echo_filter_.client_filter()),
38 capturer_(capturer), 51 max_duration_(max_duration),
39 max_duration_(max_duration) { 52 capture_task_runner_(capture_task_runner),
53 encode_task_runner_(encode_task_runner),
54 network_task_runner_(network_task_runner),
55 active_recorders_(0) {
40 connection_->SetEventHandler(this); 56 connection_->SetEventHandler(this);
41 57
42 // TODO(sergeyu): Currently ConnectionToClient expects stubs to be 58 // TODO(sergeyu): Currently ConnectionToClient expects stubs to be
43 // set before channels are connected. Make it possible to set stubs 59 // set before channels are connected. Make it possible to set stubs
44 // later and set them only when connection is authenticated. 60 // later and set them only when connection is authenticated.
45 connection_->set_clipboard_stub(&auth_clipboard_filter_); 61 connection_->set_clipboard_stub(&auth_clipboard_filter_);
46 connection_->set_host_stub(this); 62 connection_->set_host_stub(this);
47 connection_->set_input_stub(&auth_input_filter_); 63 connection_->set_input_stub(&auth_input_filter_);
48 clipboard_echo_filter_.set_host_stub(host_clipboard_stub_); 64 clipboard_echo_filter_.set_host_stub(host_clipboard_stub_);
49 65
50 // |auth_*_filter_|'s states reflect whether the session is authenticated. 66 // |auth_*_filter_|'s states reflect whether the session is authenticated.
51 auth_input_filter_.set_enabled(false); 67 auth_input_filter_.set_enabled(false);
52 auth_clipboard_filter_.set_enabled(false); 68 auth_clipboard_filter_.set_enabled(false);
53 } 69 }
54 70
55 ClientSession::~ClientSession() {
56 }
57
58 void ClientSession::NotifyClientDimensions( 71 void ClientSession::NotifyClientDimensions(
59 const protocol::ClientDimensions& dimensions) { 72 const protocol::ClientDimensions& dimensions) {
60 // TODO(wez): Use the dimensions, e.g. to resize the host desktop to match. 73 // TODO(wez): Use the dimensions, e.g. to resize the host desktop to match.
61 if (dimensions.has_width() && dimensions.has_height()) { 74 if (dimensions.has_width() && dimensions.has_height()) {
62 VLOG(1) << "Received ClientDimensions (width=" 75 VLOG(1) << "Received ClientDimensions (width="
63 << dimensions.width() << ", height=" << dimensions.height() << ")"; 76 << dimensions.width() << ", height=" << dimensions.height() << ")";
64 } 77 }
65 } 78 }
66 79
67 void ClientSession::ControlVideo(const protocol::VideoControl& video_control) { 80 void ClientSession::ControlVideo(const protocol::VideoControl& video_control) {
(...skipping 23 matching lines...) Expand all
91 } 104 }
92 105
93 event_handler_->OnSessionAuthenticated(this); 106 event_handler_->OnSessionAuthenticated(this);
94 } 107 }
95 108
96 void ClientSession::OnConnectionChannelsConnected( 109 void ClientSession::OnConnectionChannelsConnected(
97 protocol::ConnectionToClient* connection) { 110 protocol::ConnectionToClient* connection) {
98 DCHECK(CalledOnValidThread()); 111 DCHECK(CalledOnValidThread());
99 DCHECK_EQ(connection_.get(), connection); 112 DCHECK_EQ(connection_.get(), connection);
100 SetDisableInputs(false); 113 SetDisableInputs(false);
114
115 // Create a ScreenRecorder, passing the message loops that it should run on.
116 VideoEncoder* video_encoder =
117 CreateVideoEncoder(connection_->session()->config());
118 video_recorder_ = new ScreenRecorder(capture_task_runner_,
119 encode_task_runner_,
120 network_task_runner_,
121 desktop_environment_->video_capturer(),
122 video_encoder);
123 ++active_recorders_;
124
125 if (connection_->session()->config().is_audio_enabled()) {
126 scoped_ptr<AudioEncoder> audio_encoder =
127 CreateAudioEncoder(connection_->session()->config());
128 audio_scheduler_ = new AudioScheduler(
129 capture_task_runner_,
130 network_task_runner_,
131 desktop_environment_->audio_capturer(),
132 audio_encoder.Pass(),
133 connection_->audio_stub());
134 ++active_recorders_;
135 }
136
137 // Start the session.
138 video_recorder_->AddConnection(connection_.get());
139 video_recorder_->Start();
140 desktop_environment_->Start(CreateClipboardProxy());
141
101 event_handler_->OnSessionChannelsConnected(this); 142 event_handler_->OnSessionChannelsConnected(this);
102 } 143 }
103 144
104 void ClientSession::OnConnectionClosed( 145 void ClientSession::OnConnectionClosed(
105 protocol::ConnectionToClient* connection, 146 protocol::ConnectionToClient* connection,
106 protocol::ErrorCode error) { 147 protocol::ErrorCode error) {
107 DCHECK(CalledOnValidThread()); 148 DCHECK(CalledOnValidThread());
108 DCHECK_EQ(connection_.get(), connection); 149 DCHECK_EQ(connection_.get(), connection);
109 150
110 if (!auth_input_filter_.enabled()) 151 if (!auth_input_filter_.enabled())
111 event_handler_->OnSessionAuthenticationFailed(this); 152 event_handler_->OnSessionAuthenticationFailed(this);
112 153
113 // Block any further input events from the client. 154 // Block any further input events from the client.
114 // TODO(wez): Fix ChromotingHost::OnSessionClosed not to check our 155 // TODO(wez): Fix ChromotingHost::OnSessionClosed not to check our
115 // is_authenticated(), so that we can disable |auth_*_filter_| here. 156 // is_authenticated(), so that we can disable |auth_*_filter_| here.
116 disable_input_filter_.set_enabled(false); 157 disable_input_filter_.set_enabled(false);
117 disable_clipboard_filter_.set_enabled(false); 158 disable_clipboard_filter_.set_enabled(false);
118 159
119 // Ensure that any pressed keys or buttons are released. 160 // Ensure that any pressed keys or buttons are released.
120 input_tracker_.ReleaseAll(); 161 input_tracker_.ReleaseAll();
121 162
122 // TODO(sergeyu): Log failure reason? 163 // TODO(sergeyu): Log failure reason?
123 event_handler_->OnSessionClosed(this); 164 event_handler_->OnSessionClosed(this);
124 } 165 }
125 166
126 void ClientSession::OnSequenceNumberUpdated( 167 void ClientSession::OnSequenceNumberUpdated(
127 protocol::ConnectionToClient* connection, int64 sequence_number) { 168 protocol::ConnectionToClient* connection, int64 sequence_number) {
128 DCHECK(CalledOnValidThread()); 169 DCHECK(CalledOnValidThread());
129 DCHECK_EQ(connection_.get(), connection); 170 DCHECK_EQ(connection_.get(), connection);
171
172 if (video_recorder_.get())
173 video_recorder_->UpdateSequenceNumber(sequence_number);
174
130 event_handler_->OnSessionSequenceNumber(this, sequence_number); 175 event_handler_->OnSessionSequenceNumber(this, sequence_number);
131 } 176 }
132 177
133 void ClientSession::OnRouteChange( 178 void ClientSession::OnRouteChange(
134 protocol::ConnectionToClient* connection, 179 protocol::ConnectionToClient* connection,
135 const std::string& channel_name, 180 const std::string& channel_name,
136 const protocol::TransportRoute& route) { 181 const protocol::TransportRoute& route) {
137 DCHECK(CalledOnValidThread()); 182 DCHECK(CalledOnValidThread());
138 DCHECK_EQ(connection_.get(), connection); 183 DCHECK_EQ(connection_.get(), connection);
139 event_handler_->OnSessionRouteChange(this, channel_name, route); 184 event_handler_->OnSessionRouteChange(this, channel_name, route);
140 } 185 }
141 186
142 void ClientSession::Disconnect() { 187 void ClientSession::Disconnect() {
143 DCHECK(CalledOnValidThread()); 188 DCHECK(CalledOnValidThread());
144 DCHECK(connection_.get()); 189 DCHECK(connection_.get());
145 190
146 max_duration_timer_.Stop(); 191 max_duration_timer_.Stop();
147 // This triggers OnConnectionClosed(), and the session may be destroyed 192 // This triggers OnConnectionClosed(), and the session may be destroyed
148 // as the result, so this call must be the last in this method. 193 // as the result, so this call must be the last in this method.
149 connection_->Disconnect(); 194 connection_->Disconnect();
150 } 195 }
151 196
197 void ClientSession::Stop(const base::Closure& done_task) {
198 DCHECK(CalledOnValidThread());
199 DCHECK(done_task_.is_null());
200
201 done_task_ = done_task;
202 if (audio_scheduler_.get()) {
203 audio_scheduler_->OnClientDisconnected();
204 audio_scheduler_->Stop(base::Bind(&ClientSession::OnRecorderStopped, this));
205 audio_scheduler_ = NULL;
206 }
207
208 if (video_recorder_.get()) {
209 video_recorder_->RemoveConnection(connection_.get());
210 video_recorder_->Stop(base::Bind(&ClientSession::OnRecorderStopped, this));
211 video_recorder_ = NULL;
212 }
213
214 if (!active_recorders_) {
Sergey Ulanov 2012/09/11 22:30:16 nit: remove {}
alexeypa (please no reviews) 2012/09/11 22:56:51 Done.
215 done_task_.Run();
216 }
217 }
218
152 void ClientSession::LocalMouseMoved(const SkIPoint& mouse_pos) { 219 void ClientSession::LocalMouseMoved(const SkIPoint& mouse_pos) {
153 DCHECK(CalledOnValidThread()); 220 DCHECK(CalledOnValidThread());
154 remote_input_filter_.LocalMouseMoved(mouse_pos); 221 remote_input_filter_.LocalMouseMoved(mouse_pos);
155 } 222 }
156 223
157 void ClientSession::SetDisableInputs(bool disable_inputs) { 224 void ClientSession::SetDisableInputs(bool disable_inputs) {
158 DCHECK(CalledOnValidThread()); 225 DCHECK(CalledOnValidThread());
159 226
160 if (disable_inputs) 227 if (disable_inputs)
161 input_tracker_.ReleaseAll(); 228 input_tracker_.ReleaseAll();
162 229
163 disable_input_filter_.set_enabled(!disable_inputs); 230 disable_input_filter_.set_enabled(!disable_inputs);
164 disable_clipboard_filter_.set_enabled(!disable_inputs); 231 disable_clipboard_filter_.set_enabled(!disable_inputs);
165 } 232 }
166 233
234 ClientSession::~ClientSession() {
235 DCHECK(!active_recorders_);
Sergey Ulanov 2012/09/11 22:30:16 DCHECK for thread please.
alexeypa (please no reviews) 2012/09/11 22:56:51 Done. These is a DCHECK in base::NonThreadSafe als
Sergey Ulanov 2012/09/11 23:02:41 Ah, right, sorry. Then we don't need to duplicate
236 DCHECK(audio_scheduler_.get() == NULL);
237 DCHECK(video_recorder_.get() == NULL);
238 }
239
167 scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() { 240 scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() {
168 DCHECK(CalledOnValidThread()); 241 DCHECK(CalledOnValidThread());
169 242
170 return scoped_ptr<protocol::ClipboardStub>( 243 return scoped_ptr<protocol::ClipboardStub>(
171 new protocol::ClipboardThreadProxy( 244 new protocol::ClipboardThreadProxy(
172 client_clipboard_factory_.GetWeakPtr(), 245 client_clipboard_factory_.GetWeakPtr(),
173 base::MessageLoopProxy::current())); 246 base::MessageLoopProxy::current()));
174 } 247 }
175 248
249 void ClientSession::OnRecorderStopped() {
250 if (!network_task_runner_->BelongsToCurrentThread()) {
251 network_task_runner_->PostTask(
252 FROM_HERE, base::Bind(&ClientSession::OnRecorderStopped, this));
253 return;
254 }
255
256 DCHECK(!done_task_.is_null());
257
258 --active_recorders_;
259 DCHECK_GE(active_recorders_, 0);
260
261 if (!active_recorders_) {
Sergey Ulanov 2012/09/11 22:30:16 remove {}
alexeypa (please no reviews) 2012/09/11 22:56:51 Done.
262 done_task_.Run();
263 }
264 }
265
266 // TODO(sergeyu): Move this to SessionManager?
267 // static
268 VideoEncoder* ClientSession::CreateVideoEncoder(
269 const protocol::SessionConfig& config) {
270 const protocol::ChannelConfig& video_config = config.video_config();
271
272 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
273 return VideoEncoderRowBased::CreateVerbatimEncoder();
274 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) {
275 return VideoEncoderRowBased::CreateZlibEncoder();
276 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) {
277 return new remoting::VideoEncoderVp8();
278 }
279
280 NOTIMPLEMENTED();
281 return NULL;
282 }
283
284 // static
285 scoped_ptr<AudioEncoder> ClientSession::CreateAudioEncoder(
286 const protocol::SessionConfig& config) {
287 const protocol::ChannelConfig& audio_config = config.audio_config();
288
289 if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
290 return scoped_ptr<AudioEncoder>(new AudioEncoderVerbatim());
291 } else if (audio_config.codec == protocol::ChannelConfig::CODEC_SPEEX) {
292 return scoped_ptr<AudioEncoder>(new AudioEncoderSpeex());
293 }
294
295 NOTIMPLEMENTED();
296 return scoped_ptr<AudioEncoder>(NULL);
297 }
298
299 // static
300 void ClientSessionTraits::Destruct(const ClientSession* client) {
301 client->network_task_runner_->DeleteSoon(FROM_HERE, client);
302 }
303
176 } // namespace remoting 304 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698