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

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

Issue 10911248: Revert 156297 - [Chromoting] Refactoring DesktopEnvironment and moving screen/audio recorders to Cl… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: 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
« no previous file with comments | « remoting/host/chromoting_host.h ('k') | remoting/host/chromoting_host_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/chromoting_host.h" 5 #include "remoting/host/chromoting_host.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop_proxy.h" 10 #include "base/message_loop_proxy.h"
11 #include "build/build_config.h" 11 #include "build/build_config.h"
12 #include "remoting/base/constants.h" 12 #include "remoting/base/constants.h"
13 #include "remoting/codec/audio_encoder.h"
14 #include "remoting/codec/audio_encoder_speex.h"
15 #include "remoting/codec/audio_encoder_verbatim.h"
16 #include "remoting/codec/video_encoder.h"
17 #include "remoting/codec/video_encoder_row_based.h"
18 #include "remoting/codec/video_encoder_vp8.h"
19 #include "remoting/host/audio_capturer.h"
20 #include "remoting/host/audio_scheduler.h"
13 #include "remoting/host/chromoting_host_context.h" 21 #include "remoting/host/chromoting_host_context.h"
14 #include "remoting/host/desktop_environment.h" 22 #include "remoting/host/desktop_environment.h"
15 #include "remoting/host/desktop_environment_factory.h"
16 #include "remoting/host/event_executor.h" 23 #include "remoting/host/event_executor.h"
17 #include "remoting/host/host_config.h" 24 #include "remoting/host/host_config.h"
25 #include "remoting/host/screen_recorder.h"
18 #include "remoting/protocol/connection_to_client.h" 26 #include "remoting/protocol/connection_to_client.h"
19 #include "remoting/protocol/client_stub.h" 27 #include "remoting/protocol/client_stub.h"
20 #include "remoting/protocol/host_stub.h" 28 #include "remoting/protocol/host_stub.h"
21 #include "remoting/protocol/input_stub.h" 29 #include "remoting/protocol/input_stub.h"
22 #include "remoting/protocol/session_config.h" 30 #include "remoting/protocol/session_config.h"
23 31
24 using remoting::protocol::ConnectionToClient; 32 using remoting::protocol::ConnectionToClient;
25 using remoting::protocol::InputStub; 33 using remoting::protocol::InputStub;
26 34
27 namespace remoting { 35 namespace remoting {
(...skipping 24 matching lines...) Expand all
52 60
53 // Don't use initial delay unless the last request was an error. 61 // Don't use initial delay unless the last request was an error.
54 false, 62 false,
55 }; 63 };
56 64
57 } // namespace 65 } // namespace
58 66
59 ChromotingHost::ChromotingHost( 67 ChromotingHost::ChromotingHost(
60 ChromotingHostContext* context, 68 ChromotingHostContext* context,
61 SignalStrategy* signal_strategy, 69 SignalStrategy* signal_strategy,
62 DesktopEnvironmentFactory* desktop_environment_factory, 70 DesktopEnvironment* environment,
63 scoped_ptr<protocol::SessionManager> session_manager) 71 scoped_ptr<protocol::SessionManager> session_manager)
64 : context_(context), 72 : context_(context),
65 desktop_environment_factory_(desktop_environment_factory), 73 desktop_environment_(environment),
66 session_manager_(session_manager.Pass()), 74 session_manager_(session_manager.Pass()),
67 signal_strategy_(signal_strategy), 75 signal_strategy_(signal_strategy),
68 clients_count_(0), 76 stopping_recorders_(0),
69 state_(kInitial), 77 state_(kInitial),
70 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), 78 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()),
71 login_backoff_(&kDefaultBackoffPolicy), 79 login_backoff_(&kDefaultBackoffPolicy),
72 authenticating_client_(false), 80 authenticating_client_(false),
73 reject_authenticating_client_(false) { 81 reject_authenticating_client_(false) {
74 DCHECK(context_); 82 DCHECK(context_);
75 DCHECK(signal_strategy); 83 DCHECK(signal_strategy);
84 DCHECK(desktop_environment_);
76 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 85 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
77 86
78 if (!desktop_environment_factory_->SupportsAudioCapture()) { 87 if (!AudioCapturer::IsSupported()) {
79 // Disable audio by replacing our list of supported audio configurations 88 // Disable audio by replacing our list of supported audio configurations
80 // with the NONE config. 89 // with the NONE config.
81 protocol_config_->mutable_audio_configs()->clear(); 90 protocol_config_->mutable_audio_configs()->clear();
82 protocol_config_->mutable_audio_configs()->push_back( 91 protocol_config_->mutable_audio_configs()->push_back(
83 protocol::ChannelConfig()); 92 protocol::ChannelConfig());
84 } 93 }
85 } 94 }
86 95
87 ChromotingHost::~ChromotingHost() { 96 ChromotingHost::~ChromotingHost() {
88 DCHECK(clients_.empty()); 97 DCHECK(clients_.empty());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 // We are already stopping. Just save the task. 135 // We are already stopping. Just save the task.
127 if (!shutdown_task.is_null()) 136 if (!shutdown_task.is_null())
128 shutdown_tasks_.push_back(shutdown_task); 137 shutdown_tasks_.push_back(shutdown_task);
129 break; 138 break;
130 139
131 case kStarted: 140 case kStarted:
132 if (!shutdown_task.is_null()) 141 if (!shutdown_task.is_null())
133 shutdown_tasks_.push_back(shutdown_task); 142 shutdown_tasks_.push_back(shutdown_task);
134 state_ = kStopping; 143 state_ = kStopping;
135 144
136 // Disconnect all of the clients. 145 // Disconnect all of the clients, implicitly stopping the ScreenRecorder.
137 while (!clients_.empty()) { 146 while (!clients_.empty()) {
138 clients_.front()->Disconnect(); 147 clients_.front()->Disconnect();
139 } 148 }
149 DCHECK(!recorder_.get());
150 DCHECK(!audio_scheduler_.get());
140 151
141 // Run the remaining shutdown tasks. 152 // Destroy session manager.
142 if (state_ == kStopping && !clients_count_) 153 session_manager_.reset();
154
155 if (!stopping_recorders_)
143 ShutdownFinish(); 156 ShutdownFinish();
144
145 break; 157 break;
146 } 158 }
147 } 159 }
148 160
149 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { 161 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) {
150 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 162 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
151 status_observers_.AddObserver(observer); 163 status_observers_.AddObserver(observer);
152 } 164 }
153 165
154 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) { 166 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) {
(...skipping 23 matching lines...) Expand all
178 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 190 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
179 191
180 login_backoff_.Reset(); 192 login_backoff_.Reset();
181 193
182 // Disconnect all other clients. 194 // Disconnect all other clients.
183 // Iterate over a copy of the list of clients, to avoid mutating the list 195 // Iterate over a copy of the list of clients, to avoid mutating the list
184 // while iterating over it. 196 // while iterating over it.
185 ClientList clients_copy(clients_); 197 ClientList clients_copy(clients_);
186 for (ClientList::const_iterator other_client = clients_copy.begin(); 198 for (ClientList::const_iterator other_client = clients_copy.begin();
187 other_client != clients_copy.end(); ++other_client) { 199 other_client != clients_copy.end(); ++other_client) {
188 if (other_client->get() != client) { 200 if ((*other_client) != client) {
189 (*other_client)->Disconnect(); 201 (*other_client)->Disconnect();
190 } 202 }
191 } 203 }
192 204
193 // Disconnects above must have destroyed all other clients and |recorder_|. 205 // Disconnects above must have destroyed all other clients and |recorder_|.
194 DCHECK_EQ(clients_.size(), 1U); 206 DCHECK_EQ(clients_.size(), 1U);
207 DCHECK(!recorder_.get());
208 DCHECK(!audio_scheduler_.get());
195 209
196 // Notify observers that there is at least one authenticated client. 210 // Notify observers that there is at least one authenticated client.
197 const std::string& jid = client->client_jid(); 211 const std::string& jid = client->client_jid();
198 212
199 reject_authenticating_client_ = false; 213 reject_authenticating_client_ = false;
200 214
201 authenticating_client_ = true; 215 authenticating_client_ = true;
202 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 216 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
203 OnClientAuthenticated(jid)); 217 OnClientAuthenticated(jid));
204 authenticating_client_ = false; 218 authenticating_client_ = false;
205 219
206 if (reject_authenticating_client_) { 220 if (reject_authenticating_client_) {
207 client->Disconnect(); 221 client->Disconnect();
208 } 222 }
209 } 223 }
210 224
211 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) { 225 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) {
212 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 226 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
213 227
214 // Notify observers. 228 // Then we create a ScreenRecorder passing the message loops that
229 // it should run on.
230 VideoEncoder* video_encoder =
231 CreateVideoEncoder(client->connection()->session()->config());
232
233 recorder_ = new ScreenRecorder(context_->capture_task_runner(),
234 context_->encode_task_runner(),
235 context_->network_task_runner(),
236 desktop_environment_->capturer(),
237 video_encoder);
238 if (client->connection()->session()->config().is_audio_enabled()) {
239 scoped_ptr<AudioEncoder> audio_encoder =
240 CreateAudioEncoder(client->connection()->session()->config());
241 audio_scheduler_ = new AudioScheduler(
242 context_->audio_task_runner(),
243 context_->network_task_runner(),
244 desktop_environment_->audio_capturer(),
245 audio_encoder.Pass(),
246 client->connection()->audio_stub());
247 }
248
249 // Immediately add the connection and start the session.
250 recorder_->AddConnection(client->connection());
251 recorder_->Start();
252 desktop_environment_->OnSessionStarted(client->CreateClipboardProxy());
253
215 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 254 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
216 OnClientConnected(client->client_jid())); 255 OnClientConnected(client->client_jid()));
217 } 256 }
218 257
219 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) { 258 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) {
220 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 259 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
221 260
222 // Notify observers. 261 // Notify observers.
223 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 262 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
224 OnAccessDenied(client->client_jid())); 263 OnAccessDenied(client->client_jid()));
225 } 264 }
226 265
227 void ChromotingHost::OnSessionClosed(ClientSession* client) { 266 void ChromotingHost::OnSessionClosed(ClientSession* client) {
228 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 267 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
229 268
230 ClientList::iterator it = clients_.begin(); 269 scoped_ptr<ClientSession> client_destroyer(client);
231 for (; it != clients_.end(); ++it) { 270
232 if (it->get() == client) { 271 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client);
233 break; 272 CHECK(it != clients_.end());
234 } 273 clients_.erase(it);
274
275 if (recorder_.get()) {
276 recorder_->RemoveConnection(client->connection());
235 } 277 }
236 CHECK(it != clients_.end()); 278
279 if (audio_scheduler_.get()) {
280 audio_scheduler_->OnClientDisconnected();
281 StopAudioScheduler();
282 }
237 283
238 if (client->is_authenticated()) { 284 if (client->is_authenticated()) {
239 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 285 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
240 OnClientDisconnected(client->client_jid())); 286 OnClientDisconnected(client->client_jid()));
287
288 // TODO(sergeyu): This teardown logic belongs to ClientSession
289 // class. It should start/stop screen recorder or tell the host
290 // when to do it.
291 if (recorder_.get()) {
292 // Currently we don't allow more than one simultaneous connection,
293 // so we need to shutdown recorder when a client disconnects.
294 StopScreenRecorder();
295 }
296 desktop_environment_->OnSessionFinished();
241 } 297 }
242
243 client->Stop(base::Bind(&ChromotingHost::OnClientStopped, this));
244 clients_.erase(it);
245 } 298 }
246 299
247 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session, 300 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session,
248 int64 sequence_number) { 301 int64 sequence_number) {
249 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 302 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
303 if (recorder_.get())
304 recorder_->UpdateSequenceNumber(sequence_number);
250 } 305 }
251 306
252 void ChromotingHost::OnSessionRouteChange( 307 void ChromotingHost::OnSessionRouteChange(
253 ClientSession* session, 308 ClientSession* session,
254 const std::string& channel_name, 309 const std::string& channel_name,
255 const protocol::TransportRoute& route) { 310 const protocol::TransportRoute& route) {
256 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 311 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
257 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 312 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
258 OnClientRouteChange(session->client_jid(), channel_name, 313 OnClientRouteChange(session->client_jid(), channel_name,
259 route)); 314 route));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 *response = protocol::SessionManager::INCOMPATIBLE; 348 *response = protocol::SessionManager::INCOMPATIBLE;
294 return; 349 return;
295 } 350 }
296 351
297 session->set_config(config); 352 session->set_config(config);
298 353
299 *response = protocol::SessionManager::ACCEPT; 354 *response = protocol::SessionManager::ACCEPT;
300 355
301 LOG(INFO) << "Client connected: " << session->jid(); 356 LOG(INFO) << "Client connected: " << session->jid();
302 357
303 // Create the desktop integration implementation for the client to use.
304 scoped_ptr<DesktopEnvironment> desktop_environment =
305 desktop_environment_factory_->Create(context_);
306
307 // Create a client object. 358 // Create a client object.
308 scoped_ptr<protocol::ConnectionToClient> connection( 359 scoped_ptr<protocol::ConnectionToClient> connection(
309 new protocol::ConnectionToClient(session)); 360 new protocol::ConnectionToClient(session));
310 scoped_refptr<ClientSession> client = new ClientSession( 361 ClientSession* client = new ClientSession(
311 this, 362 this,
312 context_->capture_task_runner(),
313 context_->encode_task_runner(),
314 context_->network_task_runner(),
315 connection.Pass(), 363 connection.Pass(),
316 desktop_environment.Pass(), 364 desktop_environment_->event_executor(),
365 desktop_environment_->event_executor(),
366 desktop_environment_->capturer(),
317 max_session_duration_); 367 max_session_duration_);
318 clients_.push_back(client); 368 clients_.push_back(client);
319 clients_count_++;
320 } 369 }
321 370
322 void ChromotingHost::set_protocol_config( 371 void ChromotingHost::set_protocol_config(
323 protocol::CandidateSessionConfig* config) { 372 protocol::CandidateSessionConfig* config) {
324 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 373 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
325 DCHECK(config); 374 DCHECK(config);
326 DCHECK_EQ(state_, kInitial); 375 DCHECK_EQ(state_, kInitial);
327 protocol_config_.reset(config); 376 protocol_config_.reset(config);
328 } 377 }
329 378
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } 417 }
369 } 418 }
370 419
371 void ChromotingHost::SetUiStrings(const UiStrings& ui_strings) { 420 void ChromotingHost::SetUiStrings(const UiStrings& ui_strings) {
372 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 421 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
373 DCHECK_EQ(state_, kInitial); 422 DCHECK_EQ(state_, kInitial);
374 423
375 ui_strings_ = ui_strings; 424 ui_strings_ = ui_strings;
376 } 425 }
377 426
378 void ChromotingHost::OnClientStopped() { 427 // TODO(sergeyu): Move this to SessionManager?
428 // static
429 VideoEncoder* ChromotingHost::CreateVideoEncoder(
430 const protocol::SessionConfig& config) {
431 const protocol::ChannelConfig& video_config = config.video_config();
432
433 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
434 return VideoEncoderRowBased::CreateVerbatimEncoder();
435 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) {
436 return VideoEncoderRowBased::CreateZlibEncoder();
437 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) {
438 return new remoting::VideoEncoderVp8();
439 }
440
441 return NULL;
442 }
443
444 // static
445 scoped_ptr<AudioEncoder> ChromotingHost::CreateAudioEncoder(
446 const protocol::SessionConfig& config) {
447 const protocol::ChannelConfig& audio_config = config.audio_config();
448
449 if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
450 return scoped_ptr<AudioEncoder>(new AudioEncoderVerbatim());
451 } else if (audio_config.codec == protocol::ChannelConfig::CODEC_SPEEX) {
452 return scoped_ptr<AudioEncoder>(new AudioEncoderSpeex());
453 }
454
455 NOTIMPLEMENTED();
456 return scoped_ptr<AudioEncoder>(NULL);
457 }
458
459 void ChromotingHost::StopScreenRecorder() {
379 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 460 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
461 DCHECK(recorder_.get());
380 462
381 --clients_count_; 463 ++stopping_recorders_;
382 if (state_ == kStopping && !clients_count_) 464 scoped_refptr<ScreenRecorder> recorder = recorder_;
465 recorder_ = NULL;
466 recorder->Stop(base::Bind(&ChromotingHost::OnRecorderStopped, this));
467 }
468
469 void ChromotingHost::StopAudioScheduler() {
470 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
471 DCHECK(audio_scheduler_.get());
472
473 ++stopping_recorders_;
474 scoped_refptr<AudioScheduler> recorder = audio_scheduler_;
475 audio_scheduler_ = NULL;
476 recorder->Stop(base::Bind(&ChromotingHost::OnRecorderStopped, this));
477 }
478
479 void ChromotingHost::OnRecorderStopped() {
480 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
481 context_->network_task_runner()->PostTask(
482 FROM_HERE, base::Bind(&ChromotingHost::OnRecorderStopped, this));
483 return;
484 }
485
486 --stopping_recorders_;
487 DCHECK_GE(stopping_recorders_, 0);
488
489 if (!stopping_recorders_ && state_ == kStopping)
383 ShutdownFinish(); 490 ShutdownFinish();
384 } 491 }
385 492
386 void ChromotingHost::ShutdownFinish() { 493 void ChromotingHost::ShutdownFinish() {
387 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 494 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
388 DCHECK_EQ(state_, kStopping); 495 DCHECK(!stopping_recorders_);
389
390 // Destroy session manager.
391 session_manager_.reset();
392 496
393 state_ = kStopped; 497 state_ = kStopped;
394 498
395 // Keep reference to |this|, so that we don't get destroyed while 499 // Keep reference to |this|, so that we don't get destroyed while
396 // sending notifications. 500 // sending notifications.
397 scoped_refptr<ChromotingHost> self(this); 501 scoped_refptr<ChromotingHost> self(this);
398 502
399 // Notify observers. 503 // Notify observers.
400 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 504 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
401 OnShutdown()); 505 OnShutdown());
402 506
403 for (std::vector<base::Closure>::iterator it = shutdown_tasks_.begin(); 507 for (std::vector<base::Closure>::iterator it = shutdown_tasks_.begin();
404 it != shutdown_tasks_.end(); ++it) { 508 it != shutdown_tasks_.end(); ++it) {
405 it->Run(); 509 it->Run();
406 } 510 }
407 shutdown_tasks_.clear(); 511 shutdown_tasks_.clear();
408 } 512 }
409 513
410 } // namespace remoting 514 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/chromoting_host.h ('k') | remoting/host/chromoting_host_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698