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 ShutdownNetwork(); | 146 ShutdownNetwork(); |
163 } | 147 } |
164 | 148 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 FROM_HERE, | 339 FROM_HERE, |
356 NewRunnableMethod(this, | 340 NewRunnableMethod(this, |
357 &ChromotingHost::PauseSession, | 341 &ChromotingHost::PauseSession, |
358 pause)); | 342 pause)); |
359 return; | 343 return; |
360 } | 344 } |
361 ClientList::iterator client; | 345 ClientList::iterator client; |
362 for (client = clients_.begin(); client != clients_.end(); ++client) { | 346 for (client = clients_.begin(); client != clients_.end(); ++client) { |
363 client->get()->set_awaiting_continue_approval(pause); | 347 client->get()->set_awaiting_continue_approval(pause); |
364 } | 348 } |
365 StartContinueWindowTimer(!pause); | 349 desktop_environment_->OnPause(!pause); |
366 } | 350 } |
367 | 351 |
368 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { | 352 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { |
369 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 353 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
370 | 354 |
371 // Find the client session corresponding to the given connection. | 355 // Find the client session corresponding to the given connection. |
372 ClientList::iterator client; | 356 ClientList::iterator client; |
373 for (client = clients_.begin(); client != clients_.end(); ++client) { | 357 for (client = clients_.begin(); client != clients_.end(); ++client) { |
374 if (client->get()->connection() == connection) | 358 if (client->get()->connection() == connection) |
375 break; | 359 break; |
(...skipping 26 matching lines...) Expand all Loading... |
402 for (StatusObserverList::iterator it = status_observers_.begin(); | 386 for (StatusObserverList::iterator it = status_observers_.begin(); |
403 it != status_observers_.end(); ++it) { | 387 it != status_observers_.end(); ++it) { |
404 (*it)->OnAuthenticatedClientsChanged(authenticated_clients); | 388 (*it)->OnAuthenticatedClientsChanged(authenticated_clients); |
405 } | 389 } |
406 } | 390 } |
407 | 391 |
408 // Disable the "curtain" if there are no more active clients. | 392 // Disable the "curtain" if there are no more active clients. |
409 if (AuthenticatedClientsCount() == 0) { | 393 if (AuthenticatedClientsCount() == 0) { |
410 EnableCurtainMode(false); | 394 EnableCurtainMode(false); |
411 if (is_it2me_) { | 395 if (is_it2me_) { |
412 MonitorLocalInputs(false); | 396 desktop_environment_->OnLastDisconnect(); |
413 ShowDisconnectWindow(false, std::string()); | |
414 ShowContinueWindow(false); | |
415 StartContinueWindowTimer(false); | |
416 } | 397 } |
417 } | 398 } |
418 } | 399 } |
419 | 400 |
420 // TODO(sergeyu): Move this to SessionManager? | 401 // TODO(sergeyu): Move this to SessionManager? |
421 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig* config) { | 402 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig* config) { |
422 const protocol::ChannelConfig& video_config = config->video_config(); | 403 const protocol::ChannelConfig& video_config = config->video_config(); |
423 | 404 |
424 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { | 405 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { |
425 return EncoderRowBased::CreateVerbatimEncoder(); | 406 return EncoderRowBased::CreateVerbatimEncoder(); |
(...skipping 29 matching lines...) Expand all Loading... |
455 void ChromotingHost::EnableCurtainMode(bool enable) { | 436 void ChromotingHost::EnableCurtainMode(bool enable) { |
456 // TODO(jamiewalch): This will need to be more sophisticated when we think | 437 // TODO(jamiewalch): This will need to be more sophisticated when we think |
457 // about proper crash recovery and daemon mode. | 438 // about proper crash recovery and daemon mode. |
458 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. | 439 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. |
459 if (is_it2me_ || enable == is_curtained_) | 440 if (is_it2me_ || enable == is_curtained_) |
460 return; | 441 return; |
461 desktop_environment_->curtain()->EnableCurtainMode(enable); | 442 desktop_environment_->curtain()->EnableCurtainMode(enable); |
462 is_curtained_ = enable; | 443 is_curtained_ = enable; |
463 } | 444 } |
464 | 445 |
465 void ChromotingHost::MonitorLocalInputs(bool enable) { | |
466 if (enable == is_monitoring_local_inputs_) | |
467 return; | |
468 if (enable) { | |
469 desktop_environment_->local_input_monitor()->Start(this); | |
470 } else { | |
471 desktop_environment_->local_input_monitor()->Stop(); | |
472 } | |
473 is_monitoring_local_inputs_ = enable; | |
474 } | |
475 | |
476 void ChromotingHost::LocalLoginSucceeded( | 446 void ChromotingHost::LocalLoginSucceeded( |
477 scoped_refptr<ConnectionToClient> connection) { | 447 scoped_refptr<ConnectionToClient> connection) { |
478 if (MessageLoop::current() != context_->main_message_loop()) { | 448 if (MessageLoop::current() != context_->main_message_loop()) { |
479 context_->main_message_loop()->PostTask( | 449 context_->main_message_loop()->PostTask( |
480 FROM_HERE, base::Bind(&ChromotingHost::LocalLoginSucceeded, this, | 450 FROM_HERE, base::Bind(&ChromotingHost::LocalLoginSucceeded, this, |
481 connection)); | 451 connection)); |
482 return; | 452 return; |
483 } | 453 } |
484 | 454 |
485 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); | 455 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); |
(...skipping 28 matching lines...) Expand all Loading... |
514 encoder); | 484 encoder); |
515 } | 485 } |
516 | 486 |
517 // Immediately add the connection and start the session. | 487 // Immediately add the connection and start the session. |
518 recorder_->AddConnection(connection); | 488 recorder_->AddConnection(connection); |
519 recorder_->Start(); | 489 recorder_->Start(); |
520 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, | 490 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, |
521 // including closing the connection on failure of a critical operation. | 491 // including closing the connection on failure of a critical operation. |
522 EnableCurtainMode(true); | 492 EnableCurtainMode(true); |
523 if (is_it2me_) { | 493 if (is_it2me_) { |
524 MonitorLocalInputs(true); | |
525 std::string username = connection->session()->jid(); | 494 std::string username = connection->session()->jid(); |
526 size_t pos = username.find('/'); | 495 size_t pos = username.find('/'); |
527 if (pos != std::string::npos) | 496 if (pos != std::string::npos) |
528 username.replace(pos, std::string::npos, ""); | 497 username.replace(pos, std::string::npos, ""); |
529 ShowDisconnectWindow(true, username); | 498 desktop_environment_->OnConnect(username); |
530 StartContinueWindowTimer(true); | |
531 } | 499 } |
532 | 500 |
533 // Notify observers that there is at least one authenticated client. | 501 // Notify observers that there is at least one authenticated client. |
534 for (StatusObserverList::iterator it = status_observers_.begin(); | 502 for (StatusObserverList::iterator it = status_observers_.begin(); |
535 it != status_observers_.end(); ++it) { | 503 it != status_observers_.end(); ++it) { |
536 (*it)->OnAuthenticatedClientsChanged(AuthenticatedClientsCount()); | 504 (*it)->OnAuthenticatedClientsChanged(AuthenticatedClientsCount()); |
537 } | 505 } |
538 } | 506 } |
539 | 507 |
540 void ChromotingHost::LocalLoginFailed( | 508 void ChromotingHost::LocalLoginFailed( |
(...skipping 17 matching lines...) Expand all Loading... |
558 // Find the client session corresponding to the given connection. | 526 // Find the client session corresponding to the given connection. |
559 ClientList::iterator client; | 527 ClientList::iterator client; |
560 for (client = clients_.begin(); client != clients_.end(); ++client) { | 528 for (client = clients_.begin(); client != clients_.end(); ++client) { |
561 if (client->get()->connection() == connection) | 529 if (client->get()->connection() == connection) |
562 break; | 530 break; |
563 } | 531 } |
564 CHECK(client != clients_.end()); | 532 CHECK(client != clients_.end()); |
565 client->get()->OnAuthorizationComplete(true); | 533 client->get()->OnAuthorizationComplete(true); |
566 } | 534 } |
567 | 535 |
568 void ChromotingHost::ShowDisconnectWindow(bool show, | |
569 const std::string& username) { | |
570 if (!context_->IsUIThread()) { | |
571 context_->PostToUIThread( | |
572 FROM_HERE, | |
573 NewRunnableMethod(this, &ChromotingHost::ShowDisconnectWindow, | |
574 show, username)); | |
575 return; | |
576 } | |
577 | |
578 if (show) { | |
579 desktop_environment_->disconnect_window()->Show(this, username); | |
580 } else { | |
581 desktop_environment_->disconnect_window()->Hide(); | |
582 } | |
583 } | |
584 | |
585 void ChromotingHost::ShowContinueWindow(bool show) { | |
586 if (!context_->IsUIThread()) { | |
587 context_->PostToUIThread( | |
588 FROM_HERE, | |
589 NewRunnableMethod(this, &ChromotingHost::ShowContinueWindow, show)); | |
590 return; | |
591 } | |
592 | |
593 if (show) { | |
594 desktop_environment_->continue_window()->Show(this); | |
595 } else { | |
596 desktop_environment_->continue_window()->Hide(); | |
597 } | |
598 } | |
599 | |
600 void ChromotingHost::StartContinueWindowTimer(bool start) { | |
601 if (context_->main_message_loop() != MessageLoop::current()) { | |
602 context_->main_message_loop()->PostTask( | |
603 FROM_HERE, | |
604 NewRunnableMethod(this, | |
605 &ChromotingHost::StartContinueWindowTimer, | |
606 start)); | |
607 return; | |
608 } | |
609 if (continue_window_timer_.IsRunning() == start) | |
610 return; | |
611 if (start) { | |
612 continue_window_timer_.Start( | |
613 base::TimeDelta::FromSeconds(kContinueWindowTimeoutSecs), | |
614 this, &ChromotingHost::ContinueWindowTimerFunc); | |
615 } else { | |
616 continue_window_timer_.Stop(); | |
617 } | |
618 } | |
619 | |
620 void ChromotingHost::ContinueWindowTimerFunc() { | |
621 PauseSession(true); | |
622 ShowContinueWindow(true); | |
623 } | |
624 | |
625 void ChromotingHost::ShutdownNetwork() { | 536 void ChromotingHost::ShutdownNetwork() { |
626 if (MessageLoop::current() != context_->network_message_loop()) { | 537 if (MessageLoop::current() != context_->network_message_loop()) { |
627 context_->network_message_loop()->PostTask( | 538 context_->network_message_loop()->PostTask( |
628 FROM_HERE, base::Bind(&ChromotingHost::ShutdownNetwork, this)); | 539 FROM_HERE, base::Bind(&ChromotingHost::ShutdownNetwork, this)); |
629 return; | 540 return; |
630 } | 541 } |
631 | 542 |
632 // Stop chromotocol session manager. | 543 // Stop chromotocol session manager. |
633 if (session_manager_.get()) { | 544 if (session_manager_.get()) { |
634 session_manager_->Close(); | 545 session_manager_->Close(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 | 594 |
684 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); | 595 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); |
685 it != shutdown_tasks_.end(); ++it) { | 596 it != shutdown_tasks_.end(); ++it) { |
686 (*it)->Run(); | 597 (*it)->Run(); |
687 delete *it; | 598 delete *it; |
688 } | 599 } |
689 shutdown_tasks_.clear(); | 600 shutdown_tasks_.clear(); |
690 } | 601 } |
691 | 602 |
692 } // namespace remoting | 603 } // namespace remoting |
OLD | NEW |