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

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

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