Chromium Code Reviews| 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 "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 // Provide the Access Code as shared secret for SSL channel authentication. | 293 // Provide the Access Code as shared secret for SSL channel authentication. |
| 294 session->set_shared_secret(access_code_); | 294 session->set_shared_secret(access_code_); |
| 295 | 295 |
| 296 *response = protocol::SessionManager::ACCEPT; | 296 *response = protocol::SessionManager::ACCEPT; |
| 297 | 297 |
| 298 LOG(INFO) << "Client connected: " << session->jid(); | 298 LOG(INFO) << "Client connected: " << session->jid(); |
| 299 | 299 |
| 300 // We accept the connection, so create a connection object. | 300 // We accept the connection, so create a connection object. |
| 301 ConnectionToClient* connection = new ConnectionToClient( | 301 ConnectionToClient* connection = new ConnectionToClient( |
| 302 context_->network_message_loop(), this); | 302 context_->network_message_loop(), this); |
| 303 connection->Init(session); | |
|
Wez
2011/09/12 22:40:44
Why did this move?
Sergey Ulanov
2011/09/12 22:53:22
Because ClientSession constructor now needs to acc
| |
| 303 | 304 |
| 304 // Create a client object. | 305 // Create a client object. |
| 305 ClientSession* client = new ClientSession( | 306 ClientSession* client = new ClientSession( |
| 306 this, | 307 this, |
| 307 UserAuthenticator::Create(), | 308 UserAuthenticator::Create(), |
| 308 connection, | 309 connection, |
| 309 desktop_environment_->event_executor()); | 310 desktop_environment_->event_executor()); |
| 310 connection->set_host_stub(client); | 311 connection->set_host_stub(client); |
| 311 connection->set_input_stub(client); | 312 connection->set_input_stub(client); |
| 312 | 313 |
| 313 connection->Init(session); | |
| 314 | |
| 315 clients_.push_back(client); | 314 clients_.push_back(client); |
| 316 } | 315 } |
| 317 | 316 |
| 318 void ChromotingHost::set_protocol_config( | 317 void ChromotingHost::set_protocol_config( |
| 319 protocol::CandidateSessionConfig* config) { | 318 protocol::CandidateSessionConfig* config) { |
| 320 DCHECK(config_.get()); | 319 DCHECK(config_.get()); |
| 321 DCHECK_EQ(state_, kInitial); | 320 DCHECK_EQ(state_, kInitial); |
| 322 protocol_config_.reset(config); | 321 protocol_config_.reset(config); |
| 323 } | 322 } |
| 324 | 323 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 354 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 353 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
| 355 DCHECK_EQ(state_, kInitial); | 354 DCHECK_EQ(state_, kInitial); |
| 356 | 355 |
| 357 ui_strings_ = ui_strings; | 356 ui_strings_ = ui_strings; |
| 358 } | 357 } |
| 359 | 358 |
| 360 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { | 359 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { |
| 361 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 360 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
| 362 | 361 |
| 363 // Find the client session corresponding to the given connection. | 362 // Find the client session corresponding to the given connection. |
| 364 ClientList::iterator client; | 363 ClientList::iterator it; |
| 365 for (client = clients_.begin(); client != clients_.end(); ++client) { | 364 for (it = clients_.begin(); it != clients_.end(); ++it) { |
| 366 if (client->get()->connection() == connection) | 365 if (it->get()->connection() == connection) |
| 367 break; | 366 break; |
| 368 } | 367 } |
| 369 if (client == clients_.end()) | 368 if (it == clients_.end()) |
| 370 return; | 369 return; |
| 371 | 370 |
| 371 scoped_refptr<ClientSession> client = *it; | |
| 372 | |
| 373 clients_.erase(it); | |
| 374 | |
| 372 // Remove the connection from the session manager and stop the session. | 375 // Remove the connection from the session manager and stop the session. |
| 373 // TODO(hclam): Stop only if the last connection disconnected. | |
| 374 if (recorder_.get()) { | 376 if (recorder_.get()) { |
| 375 recorder_->RemoveConnection(connection); | 377 recorder_->RemoveConnection(connection); |
| 376 // The recorder only exists to serve the unique authenticated client. | |
| 377 // If that client has disconnected, then we can kill the recorder. | |
| 378 if (client->get()->authenticated()) | |
| 379 StopScreenRecorder(); | |
| 380 } | 378 } |
| 381 | 379 |
| 382 // Close the connection to client just to be safe. | 380 // Close the connection to client just to be safe. |
| 383 connection->Disconnect(); | 381 connection->Disconnect(); |
| 384 | 382 |
| 385 // Also remove reference to ConnectionToClient from this object. | 383 if (client->authenticated()) { |
| 386 int old_authenticated_clients = AuthenticatedClientsCount(); | |
| 387 clients_.erase(client); | |
| 388 | |
| 389 // Notify the observers of the change, if any. | |
| 390 int authenticated_clients = AuthenticatedClientsCount(); | |
| 391 if (old_authenticated_clients != authenticated_clients) { | |
| 392 for (StatusObserverList::iterator it = status_observers_.begin(); | 384 for (StatusObserverList::iterator it = status_observers_.begin(); |
| 393 it != status_observers_.end(); ++it) { | 385 it != status_observers_.end(); ++it) { |
| 394 (*it)->OnClientDisconnected(connection); | 386 (*it)->OnClientDisconnected(client->client_jid()); |
| 395 } | 387 } |
| 396 } | 388 } |
| 397 | 389 |
| 398 // Disable the "curtain" if there are no more active clients. | 390 // Disable the "curtain" if there are no more active clients. |
|
Wez
2011/09/12 22:40:44
Update this comment.
Sergey Ulanov
2011/09/12 22:53:22
Done.
| |
| 399 if (AuthenticatedClientsCount() == 0) { | 391 if (AuthenticatedClientsCount() == 0) { |
| 392 if (recorder_.get()) { | |
| 393 // The recorder only exists to serve the unique authenticated client. | |
| 394 // If that client has disconnected, then we can kill the recorder. | |
|
Wez
2011/09/12 22:40:44
Simpler to say "If there are no authenticated clie
Sergey Ulanov
2011/09/12 22:53:22
Done.
| |
| 395 if (client->authenticated()) | |
| 396 StopScreenRecorder(); | |
| 397 } | |
| 398 | |
| 400 EnableCurtainMode(false); | 399 EnableCurtainMode(false); |
| 401 if (is_it2me_) { | 400 if (is_it2me_) { |
| 402 desktop_environment_->OnLastDisconnect(); | 401 desktop_environment_->OnLastDisconnect(); |
| 403 } | 402 } |
| 404 } | 403 } |
| 405 } | 404 } |
| 406 | 405 |
| 407 // TODO(sergeyu): Move this to SessionManager? | 406 // TODO(sergeyu): Move this to SessionManager? |
| 408 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { | 407 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { |
| 409 const protocol::ChannelConfig& video_config = config.video_config(); | 408 const protocol::ChannelConfig& video_config = config.video_config(); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 440 // about proper crash recovery and daemon mode. | 439 // about proper crash recovery and daemon mode. |
| 441 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. | 440 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. |
| 442 if (is_it2me_ || enable == is_curtained_) | 441 if (is_it2me_ || enable == is_curtained_) |
| 443 return; | 442 return; |
| 444 desktop_environment_->curtain()->EnableCurtainMode(enable); | 443 desktop_environment_->curtain()->EnableCurtainMode(enable); |
| 445 is_curtained_ = enable; | 444 is_curtained_ = enable; |
| 446 } | 445 } |
| 447 | 446 |
| 448 void ChromotingHost::LocalLoginSucceeded( | 447 void ChromotingHost::LocalLoginSucceeded( |
| 449 scoped_refptr<ConnectionToClient> connection) { | 448 scoped_refptr<ConnectionToClient> connection) { |
| 450 if (MessageLoop::current() != context_->main_message_loop()) { | 449 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); |
| 451 context_->main_message_loop()->PostTask( | 450 |
| 452 FROM_HERE, base::Bind(&ChromotingHost::LocalLoginSucceeded, this, | 451 context_->main_message_loop()->PostTask( |
| 453 connection)); | 452 FROM_HERE, base::Bind(&ChromotingHost::AddAuthenticatedClient, |
| 454 return; | 453 this, connection, connection->session()->config(), |
| 455 } | 454 connection->session()->jid())); |
| 455 } | |
| 456 | |
| 457 void ChromotingHost::AddAuthenticatedClient( | |
| 458 scoped_refptr<ConnectionToClient> connection, | |
| 459 const protocol::SessionConfig& config, | |
| 460 const std::string& jid) { | |
| 461 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | |
| 456 | 462 |
| 457 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); | 463 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); |
| 458 status->set_success(true); | 464 status->set_success(true); |
| 459 connection->client_stub()->BeginSessionResponse( | 465 connection->client_stub()->BeginSessionResponse( |
| 460 status, new DeleteTask<protocol::LocalLoginStatus>(status)); | 466 status, new DeleteTask<protocol::LocalLoginStatus>(status)); |
| 461 | 467 |
| 462 // Disconnect all other clients. | 468 // Disconnect all other clients. |
| 463 // Iterate over a copy of the list of clients, to avoid mutating the list | 469 // Iterate over a copy of the list of clients, to avoid mutating the list |
| 464 // while iterating over it. | 470 // while iterating over it. |
| 465 ClientList clients_copy(clients_); | 471 ClientList clients_copy(clients_); |
| 466 for (ClientList::const_iterator client = clients_copy.begin(); | 472 for (ClientList::const_iterator client = clients_copy.begin(); |
| 467 client != clients_copy.end(); client++) { | 473 client != clients_copy.end(); client++) { |
| 468 ConnectionToClient* connection_other = client->get()->connection(); | 474 ConnectionToClient* connection_other = client->get()->connection(); |
| 469 if (connection_other != connection) { | 475 if (connection_other != connection) { |
| 470 OnClientDisconnected(connection_other); | 476 OnClientDisconnected(connection_other); |
| 471 } | 477 } |
| 472 } | 478 } |
| 473 // Those disconnections should have killed the screen recorder. | 479 // Those disconnections should have killed the screen recorder. |
| 474 CHECK(recorder_.get() == NULL); | 480 CHECK(recorder_.get() == NULL); |
| 475 | 481 |
| 476 // Create a new RecordSession if there was none. | 482 // Create a new RecordSession if there was none. |
| 477 if (!recorder_.get()) { | 483 if (!recorder_.get()) { |
| 478 // Then we create a ScreenRecorder passing the message loops that | 484 // Then we create a ScreenRecorder passing the message loops that |
| 479 // it should run on. | 485 // it should run on. |
| 480 Encoder* encoder = CreateEncoder(connection->session()->config()); | 486 Encoder* encoder = CreateEncoder(config); |
| 481 | 487 |
| 482 recorder_ = new ScreenRecorder(context_->main_message_loop(), | 488 recorder_ = new ScreenRecorder(context_->main_message_loop(), |
| 483 context_->encode_message_loop(), | 489 context_->encode_message_loop(), |
| 484 context_->network_message_loop(), | 490 context_->network_message_loop(), |
| 485 desktop_environment_->capturer(), | 491 desktop_environment_->capturer(), |
| 486 encoder); | 492 encoder); |
| 487 } | 493 } |
| 488 | 494 |
| 489 // Immediately add the connection and start the session. | 495 // Immediately add the connection and start the session. |
| 490 recorder_->AddConnection(connection); | 496 recorder_->AddConnection(connection); |
| 491 recorder_->Start(); | 497 recorder_->Start(); |
| 492 // Notify observers that there is at least one authenticated client. | 498 // Notify observers that there is at least one authenticated client. |
| 493 for (StatusObserverList::iterator it = status_observers_.begin(); | 499 for (StatusObserverList::iterator it = status_observers_.begin(); |
| 494 it != status_observers_.end(); ++it) { | 500 it != status_observers_.end(); ++it) { |
| 495 (*it)->OnClientAuthenticated(connection); | 501 (*it)->OnClientAuthenticated(jid); |
| 496 } | 502 } |
| 497 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, | 503 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, |
| 498 // including closing the connection on failure of a critical operation. | 504 // including closing the connection on failure of a critical operation. |
| 499 EnableCurtainMode(true); | 505 EnableCurtainMode(true); |
| 500 if (is_it2me_) { | 506 if (is_it2me_) { |
| 501 std::string username = connection->session()->jid(); | 507 std::string username = jid; |
| 502 size_t pos = username.find('/'); | 508 size_t pos = username.find('/'); |
| 503 if (pos != std::string::npos) | 509 if (pos != std::string::npos) |
| 504 username.replace(pos, std::string::npos, ""); | 510 username.replace(pos, std::string::npos, ""); |
| 505 desktop_environment_->OnConnect(username); | 511 desktop_environment_->OnConnect(username); |
| 506 } | 512 } |
| 507 } | 513 } |
| 508 | 514 |
| 509 void ChromotingHost::LocalLoginFailed( | 515 void ChromotingHost::LocalLoginFailed( |
| 510 scoped_refptr<ConnectionToClient> connection) { | 516 scoped_refptr<ConnectionToClient> connection) { |
| 511 if (MessageLoop::current() != context_->main_message_loop()) { | 517 if (MessageLoop::current() != context_->main_message_loop()) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 524 void ChromotingHost::ProcessPreAuthentication( | 530 void ChromotingHost::ProcessPreAuthentication( |
| 525 const scoped_refptr<ConnectionToClient>& connection) { | 531 const scoped_refptr<ConnectionToClient>& connection) { |
| 526 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 532 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
| 527 // Find the client session corresponding to the given connection. | 533 // Find the client session corresponding to the given connection. |
| 528 ClientList::iterator client; | 534 ClientList::iterator client; |
| 529 for (client = clients_.begin(); client != clients_.end(); ++client) { | 535 for (client = clients_.begin(); client != clients_.end(); ++client) { |
| 530 if (client->get()->connection() == connection) | 536 if (client->get()->connection() == connection) |
| 531 break; | 537 break; |
| 532 } | 538 } |
| 533 CHECK(client != clients_.end()); | 539 CHECK(client != clients_.end()); |
| 534 client->get()->OnAuthorizationComplete(true); | 540 |
| 541 context_->network_message_loop()->PostTask( | |
| 542 FROM_HERE, base::Bind(&ClientSession::OnAuthorizationComplete, | |
| 543 client->get(), true)); | |
| 535 } | 544 } |
| 536 | 545 |
| 537 void ChromotingHost::StopScreenRecorder() { | 546 void ChromotingHost::StopScreenRecorder() { |
| 538 DCHECK(MessageLoop::current() == context_->main_message_loop()); | 547 DCHECK(MessageLoop::current() == context_->main_message_loop()); |
| 539 DCHECK(recorder_.get()); | 548 DCHECK(recorder_.get()); |
| 540 | 549 |
| 541 ++stopping_recorders_; | 550 ++stopping_recorders_; |
| 542 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); | 551 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); |
| 543 recorder_ = NULL; | 552 recorder_ = NULL; |
| 544 } | 553 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 628 | 637 |
| 629 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); | 638 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); |
| 630 it != shutdown_tasks_.end(); ++it) { | 639 it != shutdown_tasks_.end(); ++it) { |
| 631 (*it)->Run(); | 640 (*it)->Run(); |
| 632 delete *it; | 641 delete *it; |
| 633 } | 642 } |
| 634 shutdown_tasks_.clear(); | 643 shutdown_tasks_.clear(); |
| 635 } | 644 } |
| 636 | 645 |
| 637 } // namespace remoting | 646 } // namespace remoting |
| OLD | NEW |