OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "build/build_config.h" | 9 #include "build/build_config.h" |
10 #include "remoting/base/constants.h" | 10 #include "remoting/base/constants.h" |
11 #include "remoting/base/encoder.h" | 11 #include "remoting/base/encoder.h" |
12 #include "remoting/base/encoder_row_based.h" | 12 #include "remoting/base/encoder_row_based.h" |
13 #include "remoting/base/encoder_vp8.h" | 13 #include "remoting/base/encoder_vp8.h" |
14 #include "remoting/host/capturer.h" | |
15 #include "remoting/host/chromoting_host_context.h" | 14 #include "remoting/host/chromoting_host_context.h" |
16 #include "remoting/host/continue_window.h" | |
17 #include "remoting/host/curtain.h" | 15 #include "remoting/host/curtain.h" |
18 #include "remoting/host/desktop_environment.h" | 16 #include "remoting/host/desktop_environment.h" |
19 #include "remoting/host/disconnect_window.h" | |
20 #include "remoting/host/event_executor.h" | 17 #include "remoting/host/event_executor.h" |
21 #include "remoting/host/host_config.h" | 18 #include "remoting/host/host_config.h" |
22 #include "remoting/host/host_key_pair.h" | 19 #include "remoting/host/host_key_pair.h" |
23 #include "remoting/host/local_input_monitor.h" | |
24 #include "remoting/host/screen_recorder.h" | 20 #include "remoting/host/screen_recorder.h" |
25 #include "remoting/host/user_authenticator.h" | 21 #include "remoting/host/user_authenticator.h" |
26 #include "remoting/jingle_glue/xmpp_signal_strategy.h" | 22 #include "remoting/jingle_glue/xmpp_signal_strategy.h" |
27 #include "remoting/proto/auth.pb.h" | 23 #include "remoting/proto/auth.pb.h" |
28 #include "remoting/protocol/connection_to_client.h" | 24 #include "remoting/protocol/connection_to_client.h" |
29 #include "remoting/protocol/client_stub.h" | 25 #include "remoting/protocol/client_stub.h" |
30 #include "remoting/protocol/host_stub.h" | 26 #include "remoting/protocol/host_stub.h" |
31 #include "remoting/protocol/input_stub.h" | 27 #include "remoting/protocol/input_stub.h" |
32 #include "remoting/protocol/jingle_session_manager.h" | 28 #include "remoting/protocol/jingle_session_manager.h" |
33 #include "remoting/protocol/session_config.h" | 29 #include "remoting/protocol/session_config.h" |
34 | 30 |
35 using remoting::protocol::ConnectionToClient; | 31 using remoting::protocol::ConnectionToClient; |
36 using remoting::protocol::InputStub; | 32 using remoting::protocol::InputStub; |
37 | 33 |
38 static const int kContinueWindowTimeoutSecs = 10 * 60; | |
39 | |
40 namespace remoting { | 34 namespace remoting { |
41 | 35 |
42 // static | 36 // static |
43 ChromotingHost* ChromotingHost::Create(ChromotingHostContext* context, | 37 ChromotingHost* ChromotingHost::Create(ChromotingHostContext* context, |
44 MutableHostConfig* config, | 38 MutableHostConfig* config, |
45 AccessVerifier* access_verifier) { | 39 AccessVerifier* access_verifier) { |
46 Capturer* capturer = Capturer::Create(); | 40 DesktopEnvironment* desktop_env = DesktopEnvironment::Create(context); |
47 EventExecutor* event_executor = | 41 return Create(context, config, desktop_env, access_verifier); |
48 EventExecutor::Create(context->desktop_message_loop(), capturer); | |
49 Curtain* curtain = Curtain::Create(); | |
50 DisconnectWindow* disconnect_window = DisconnectWindow::Create(); | |
51 ContinueWindow* continue_window = ContinueWindow::Create(); | |
52 LocalInputMonitor* local_input_monitor = LocalInputMonitor::Create(); | |
53 return Create(context, config, | |
54 new DesktopEnvironment(capturer, event_executor, curtain, | |
55 disconnect_window, continue_window, | |
56 local_input_monitor), | |
57 access_verifier); | |
58 } | 42 } |
59 | 43 |
60 // static | 44 // static |
61 ChromotingHost* ChromotingHost::Create(ChromotingHostContext* context, | 45 ChromotingHost* ChromotingHost::Create(ChromotingHostContext* context, |
62 MutableHostConfig* config, | 46 MutableHostConfig* config, |
63 DesktopEnvironment* environment, | 47 DesktopEnvironment* environment, |
64 AccessVerifier* access_verifier) { | 48 AccessVerifier* access_verifier) { |
65 return new ChromotingHost(context, config, environment, access_verifier); | 49 return new ChromotingHost(context, config, environment, access_verifier); |
66 } | 50 } |
67 | 51 |
68 ChromotingHost::ChromotingHost(ChromotingHostContext* context, | 52 ChromotingHost::ChromotingHost(ChromotingHostContext* context, |
69 MutableHostConfig* config, | 53 MutableHostConfig* config, |
70 DesktopEnvironment* environment, | 54 DesktopEnvironment* environment, |
71 AccessVerifier* access_verifier) | 55 AccessVerifier* access_verifier) |
72 : context_(context), | 56 : context_(context), |
73 config_(config), | 57 config_(config), |
74 desktop_environment_(environment), | 58 desktop_environment_(environment), |
75 access_verifier_(access_verifier), | 59 access_verifier_(access_verifier), |
76 state_(kInitial), | 60 state_(kInitial), |
77 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), | 61 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), |
78 is_curtained_(false), | 62 is_curtained_(false), |
79 is_monitoring_local_inputs_(false), | |
80 is_it2me_(false) { | 63 is_it2me_(false) { |
81 DCHECK(desktop_environment_.get()); | 64 DCHECK(desktop_environment_.get()); |
| 65 desktop_environment_->set_host(this); |
82 } | 66 } |
83 | 67 |
84 ChromotingHost::~ChromotingHost() { | 68 ChromotingHost::~ChromotingHost() { |
85 } | 69 } |
86 | 70 |
87 void ChromotingHost::Start() { | 71 void ChromotingHost::Start() { |
88 if (MessageLoop::current() != context_->network_message_loop()) { | 72 if (MessageLoop::current() != context_->network_message_loop()) { |
89 context_->network_message_loop()->PostTask( | 73 context_->network_message_loop()->PostTask( |
90 FROM_HERE, base::Bind(&ChromotingHost::Start, this)); | 74 FROM_HERE, base::Bind(&ChromotingHost::Start, this)); |
91 return; | 75 return; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 if (state_ == kStopping) | 127 if (state_ == kStopping) |
144 return; | 128 return; |
145 state_ = kStopping; | 129 state_ = kStopping; |
146 } | 130 } |
147 | 131 |
148 // Make sure ScreenRecorder doesn't write to the connection. | 132 // Make sure ScreenRecorder doesn't write to the connection. |
149 if (recorder_.get()) { | 133 if (recorder_.get()) { |
150 recorder_->RemoveAllConnections(); | 134 recorder_->RemoveAllConnections(); |
151 } | 135 } |
152 | 136 |
153 // Stop local inputs monitor. | 137 // Stop all desktop interaction. |
154 MonitorLocalInputs(false); | 138 desktop_environment_->OnLastDisconnect(); |
155 | 139 |
156 // Disconnect the clients. | 140 // Disconnect the clients. |
157 for (size_t i = 0; i < clients_.size(); i++) { | 141 for (size_t i = 0; i < clients_.size(); i++) { |
158 clients_[i]->Disconnect(); | 142 clients_[i]->Disconnect(); |
159 } | 143 } |
160 clients_.clear(); | 144 clients_.clear(); |
161 | 145 |
162 // Stop chromotocol session manager. | 146 // Stop chromotocol session manager. |
163 if (session_manager_.get()) { | 147 if (session_manager_.get()) { |
164 session_manager_->Close(); | 148 session_manager_->Close(); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 FROM_HERE, | 356 FROM_HERE, |
373 NewRunnableMethod(this, | 357 NewRunnableMethod(this, |
374 &ChromotingHost::PauseSession, | 358 &ChromotingHost::PauseSession, |
375 pause)); | 359 pause)); |
376 return; | 360 return; |
377 } | 361 } |
378 ClientList::iterator client; | 362 ClientList::iterator client; |
379 for (client = clients_.begin(); client != clients_.end(); ++client) { | 363 for (client = clients_.begin(); client != clients_.end(); ++client) { |
380 client->get()->set_awaiting_continue_approval(pause); | 364 client->get()->set_awaiting_continue_approval(pause); |
381 } | 365 } |
382 StartContinueWindowTimer(!pause); | 366 desktop_environment_->OnPause(!pause); |
383 } | 367 } |
384 | 368 |
385 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { | 369 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { |
386 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 370 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
387 | 371 |
388 // Find the client session corresponding to the given connection. | 372 // Find the client session corresponding to the given connection. |
389 ClientList::iterator client; | 373 ClientList::iterator client; |
390 for (client = clients_.begin(); client != clients_.end(); ++client) { | 374 for (client = clients_.begin(); client != clients_.end(); ++client) { |
391 if (client->get()->connection() == connection) | 375 if (client->get()->connection() == connection) |
392 break; | 376 break; |
(...skipping 26 matching lines...) Expand all Loading... |
419 for (StatusObserverList::iterator it = status_observers_.begin(); | 403 for (StatusObserverList::iterator it = status_observers_.begin(); |
420 it != status_observers_.end(); ++it) { | 404 it != status_observers_.end(); ++it) { |
421 (*it)->OnAuthenticatedClientsChanged(authenticated_clients); | 405 (*it)->OnAuthenticatedClientsChanged(authenticated_clients); |
422 } | 406 } |
423 } | 407 } |
424 | 408 |
425 // Disable the "curtain" if there are no more active clients. | 409 // Disable the "curtain" if there are no more active clients. |
426 if (AuthenticatedClientsCount() == 0) { | 410 if (AuthenticatedClientsCount() == 0) { |
427 EnableCurtainMode(false); | 411 EnableCurtainMode(false); |
428 if (is_it2me_) { | 412 if (is_it2me_) { |
429 MonitorLocalInputs(false); | 413 desktop_environment_->OnLastDisconnect(); |
430 ShowDisconnectWindow(false, std::string()); | |
431 ShowContinueWindow(false); | |
432 StartContinueWindowTimer(false); | |
433 } | 414 } |
434 } | 415 } |
435 } | 416 } |
436 | 417 |
437 // TODO(sergeyu): Move this to SessionManager? | 418 // TODO(sergeyu): Move this to SessionManager? |
438 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig* config) { | 419 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig* config) { |
439 const protocol::ChannelConfig& video_config = config->video_config(); | 420 const protocol::ChannelConfig& video_config = config->video_config(); |
440 | 421 |
441 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { | 422 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { |
442 return EncoderRowBased::CreateVerbatimEncoder(); | 423 return EncoderRowBased::CreateVerbatimEncoder(); |
(...skipping 29 matching lines...) Expand all Loading... |
472 void ChromotingHost::EnableCurtainMode(bool enable) { | 453 void ChromotingHost::EnableCurtainMode(bool enable) { |
473 // TODO(jamiewalch): This will need to be more sophisticated when we think | 454 // TODO(jamiewalch): This will need to be more sophisticated when we think |
474 // about proper crash recovery and daemon mode. | 455 // about proper crash recovery and daemon mode. |
475 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. | 456 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. |
476 if (is_it2me_ || enable == is_curtained_) | 457 if (is_it2me_ || enable == is_curtained_) |
477 return; | 458 return; |
478 desktop_environment_->curtain()->EnableCurtainMode(enable); | 459 desktop_environment_->curtain()->EnableCurtainMode(enable); |
479 is_curtained_ = enable; | 460 is_curtained_ = enable; |
480 } | 461 } |
481 | 462 |
482 void ChromotingHost::MonitorLocalInputs(bool enable) { | |
483 if (enable == is_monitoring_local_inputs_) | |
484 return; | |
485 if (enable) { | |
486 desktop_environment_->local_input_monitor()->Start(this); | |
487 } else { | |
488 desktop_environment_->local_input_monitor()->Stop(); | |
489 } | |
490 is_monitoring_local_inputs_ = enable; | |
491 } | |
492 | |
493 void ChromotingHost::LocalLoginSucceeded( | 463 void ChromotingHost::LocalLoginSucceeded( |
494 scoped_refptr<ConnectionToClient> connection) { | 464 scoped_refptr<ConnectionToClient> connection) { |
495 if (MessageLoop::current() != context_->main_message_loop()) { | 465 if (MessageLoop::current() != context_->main_message_loop()) { |
496 context_->main_message_loop()->PostTask( | 466 context_->main_message_loop()->PostTask( |
497 FROM_HERE, base::Bind(&ChromotingHost::LocalLoginSucceeded, this, | 467 FROM_HERE, base::Bind(&ChromotingHost::LocalLoginSucceeded, this, |
498 connection)); | 468 connection)); |
499 return; | 469 return; |
500 } | 470 } |
501 | 471 |
502 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); | 472 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); |
(...skipping 28 matching lines...) Expand all Loading... |
531 encoder); | 501 encoder); |
532 } | 502 } |
533 | 503 |
534 // Immediately add the connection and start the session. | 504 // Immediately add the connection and start the session. |
535 recorder_->AddConnection(connection); | 505 recorder_->AddConnection(connection); |
536 recorder_->Start(); | 506 recorder_->Start(); |
537 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, | 507 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, |
538 // including closing the connection on failure of a critical operation. | 508 // including closing the connection on failure of a critical operation. |
539 EnableCurtainMode(true); | 509 EnableCurtainMode(true); |
540 if (is_it2me_) { | 510 if (is_it2me_) { |
541 MonitorLocalInputs(true); | |
542 std::string username = connection->session()->jid(); | 511 std::string username = connection->session()->jid(); |
543 size_t pos = username.find('/'); | 512 size_t pos = username.find('/'); |
544 if (pos != std::string::npos) | 513 if (pos != std::string::npos) |
545 username.replace(pos, std::string::npos, ""); | 514 username.replace(pos, std::string::npos, ""); |
546 ShowDisconnectWindow(true, username); | 515 desktop_environment_->OnConnect(username); |
547 StartContinueWindowTimer(true); | |
548 } | 516 } |
549 | 517 |
550 // Notify observers that there is at least one authenticated client. | 518 // Notify observers that there is at least one authenticated client. |
551 for (StatusObserverList::iterator it = status_observers_.begin(); | 519 for (StatusObserverList::iterator it = status_observers_.begin(); |
552 it != status_observers_.end(); ++it) { | 520 it != status_observers_.end(); ++it) { |
553 (*it)->OnAuthenticatedClientsChanged(AuthenticatedClientsCount()); | 521 (*it)->OnAuthenticatedClientsChanged(AuthenticatedClientsCount()); |
554 } | 522 } |
555 } | 523 } |
556 | 524 |
557 void ChromotingHost::LocalLoginFailed( | 525 void ChromotingHost::LocalLoginFailed( |
(...skipping 17 matching lines...) Expand all Loading... |
575 // Find the client session corresponding to the given connection. | 543 // Find the client session corresponding to the given connection. |
576 ClientList::iterator client; | 544 ClientList::iterator client; |
577 for (client = clients_.begin(); client != clients_.end(); ++client) { | 545 for (client = clients_.begin(); client != clients_.end(); ++client) { |
578 if (client->get()->connection() == connection) | 546 if (client->get()->connection() == connection) |
579 break; | 547 break; |
580 } | 548 } |
581 CHECK(client != clients_.end()); | 549 CHECK(client != clients_.end()); |
582 client->get()->OnAuthorizationComplete(true); | 550 client->get()->OnAuthorizationComplete(true); |
583 } | 551 } |
584 | 552 |
585 void ChromotingHost::ShowDisconnectWindow(bool show, | |
586 const std::string& username) { | |
587 if (!context_->IsUIThread()) { | |
588 context_->PostToUIThread( | |
589 FROM_HERE, | |
590 NewRunnableMethod(this, &ChromotingHost::ShowDisconnectWindow, | |
591 show, username)); | |
592 return; | |
593 } | |
594 | |
595 if (show) { | |
596 desktop_environment_->disconnect_window()->Show(this, username); | |
597 } else { | |
598 desktop_environment_->disconnect_window()->Hide(); | |
599 } | |
600 } | |
601 | |
602 void ChromotingHost::ShowContinueWindow(bool show) { | |
603 if (!context_->IsUIThread()) { | |
604 context_->PostToUIThread( | |
605 FROM_HERE, | |
606 NewRunnableMethod(this, &ChromotingHost::ShowContinueWindow, show)); | |
607 return; | |
608 } | |
609 | |
610 if (show) { | |
611 desktop_environment_->continue_window()->Show(this); | |
612 } else { | |
613 desktop_environment_->continue_window()->Hide(); | |
614 } | |
615 } | |
616 | |
617 void ChromotingHost::StartContinueWindowTimer(bool start) { | |
618 if (context_->main_message_loop() != MessageLoop::current()) { | |
619 context_->main_message_loop()->PostTask( | |
620 FROM_HERE, | |
621 NewRunnableMethod(this, | |
622 &ChromotingHost::StartContinueWindowTimer, | |
623 start)); | |
624 return; | |
625 } | |
626 if (continue_window_timer_.IsRunning() == start) | |
627 return; | |
628 if (start) { | |
629 continue_window_timer_.Start( | |
630 base::TimeDelta::FromSeconds(kContinueWindowTimeoutSecs), | |
631 this, &ChromotingHost::ContinueWindowTimerFunc); | |
632 } else { | |
633 continue_window_timer_.Stop(); | |
634 } | |
635 } | |
636 | |
637 void ChromotingHost::ContinueWindowTimerFunc() { | |
638 PauseSession(true); | |
639 ShowContinueWindow(true); | |
640 } | |
641 | |
642 void ChromotingHost::ShutdownRecorder() { | 553 void ChromotingHost::ShutdownRecorder() { |
643 if (MessageLoop::current() != context_->main_message_loop()) { | 554 if (MessageLoop::current() != context_->main_message_loop()) { |
644 context_->main_message_loop()->PostTask( | 555 context_->main_message_loop()->PostTask( |
645 FROM_HERE, base::Bind(&ChromotingHost::ShutdownRecorder, this)); | 556 FROM_HERE, base::Bind(&ChromotingHost::ShutdownRecorder, this)); |
646 return; | 557 return; |
647 } | 558 } |
648 | 559 |
649 if (recorder_.get()) { | 560 if (recorder_.get()) { |
650 recorder_->Stop(NewRunnableMethod(this, &ChromotingHost::ShutdownFinish)); | 561 recorder_->Stop(NewRunnableMethod(this, &ChromotingHost::ShutdownFinish)); |
651 } else { | 562 } else { |
(...skipping 21 matching lines...) Expand all Loading... |
673 | 584 |
674 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); | 585 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); |
675 it != shutdown_tasks_.end(); ++it) { | 586 it != shutdown_tasks_.end(); ++it) { |
676 (*it)->Run(); | 587 (*it)->Run(); |
677 delete *it; | 588 delete *it; |
678 } | 589 } |
679 shutdown_tasks_.clear(); | 590 shutdown_tasks_.clear(); |
680 } | 591 } |
681 | 592 |
682 } // namespace remoting | 593 } // namespace remoting |
OLD | NEW |