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

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

Issue 7867019: Access Session::config() and Session::jid() on the correct thread only. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix tests Created 9 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) 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
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);
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
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
372 // Remove the connection from the session manager and stop the session. 371 scoped_refptr<ClientSession> client = *it;
373 // TODO(hclam): Stop only if the last connection disconnected. 372
373 clients_.erase(it);
374
374 if (recorder_.get()) { 375 if (recorder_.get()) {
375 recorder_->RemoveConnection(connection); 376 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 } 377 }
381 378
382 // Close the connection to client just to be safe. 379 // Close the connection to client just to be safe.
383 connection->Disconnect(); 380 connection->Disconnect();
384 381
385 // Also remove reference to ConnectionToClient from this object. 382 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(); 383 for (StatusObserverList::iterator it = status_observers_.begin();
393 it != status_observers_.end(); ++it) { 384 it != status_observers_.end(); ++it) {
394 (*it)->OnClientDisconnected(connection); 385 (*it)->OnClientDisconnected(client->client_jid());
395 } 386 }
396 } 387 }
397 388
398 // Disable the "curtain" if there are no more active clients.
399 if (AuthenticatedClientsCount() == 0) { 389 if (AuthenticatedClientsCount() == 0) {
390 if (recorder_.get()) {
391 // Stop the recorder if there are no more clients.
392 StopScreenRecorder();
393 }
394
395 // Disable the "curtain" if there are no more active clients.
400 EnableCurtainMode(false); 396 EnableCurtainMode(false);
401 if (is_it2me_) { 397 if (is_it2me_) {
402 desktop_environment_->OnLastDisconnect(); 398 desktop_environment_->OnLastDisconnect();
403 } 399 }
404 } 400 }
405 } 401 }
406 402
407 // TODO(sergeyu): Move this to SessionManager? 403 // TODO(sergeyu): Move this to SessionManager?
408 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { 404 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) {
409 const protocol::ChannelConfig& video_config = config.video_config(); 405 const protocol::ChannelConfig& video_config = config.video_config();
(...skipping 30 matching lines...) Expand all
440 // about proper crash recovery and daemon mode. 436 // about proper crash recovery and daemon mode.
441 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. 437 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost.
442 if (is_it2me_ || enable == is_curtained_) 438 if (is_it2me_ || enable == is_curtained_)
443 return; 439 return;
444 desktop_environment_->curtain()->EnableCurtainMode(enable); 440 desktop_environment_->curtain()->EnableCurtainMode(enable);
445 is_curtained_ = enable; 441 is_curtained_ = enable;
446 } 442 }
447 443
448 void ChromotingHost::LocalLoginSucceeded( 444 void ChromotingHost::LocalLoginSucceeded(
449 scoped_refptr<ConnectionToClient> connection) { 445 scoped_refptr<ConnectionToClient> connection) {
450 if (MessageLoop::current() != context_->main_message_loop()) { 446 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
451 context_->main_message_loop()->PostTask( 447
452 FROM_HERE, base::Bind(&ChromotingHost::LocalLoginSucceeded, this, 448 context_->main_message_loop()->PostTask(
453 connection)); 449 FROM_HERE, base::Bind(&ChromotingHost::AddAuthenticatedClient,
454 return; 450 this, connection, connection->session()->config(),
455 } 451 connection->session()->jid()));
452 }
453
454 void ChromotingHost::AddAuthenticatedClient(
455 scoped_refptr<ConnectionToClient> connection,
456 const protocol::SessionConfig& config,
457 const std::string& jid) {
458 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
456 459
457 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); 460 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus();
458 status->set_success(true); 461 status->set_success(true);
459 connection->client_stub()->BeginSessionResponse( 462 connection->client_stub()->BeginSessionResponse(
460 status, new DeleteTask<protocol::LocalLoginStatus>(status)); 463 status, new DeleteTask<protocol::LocalLoginStatus>(status));
461 464
462 // Disconnect all other clients. 465 // Disconnect all other clients.
463 // Iterate over a copy of the list of clients, to avoid mutating the list 466 // Iterate over a copy of the list of clients, to avoid mutating the list
464 // while iterating over it. 467 // while iterating over it.
465 ClientList clients_copy(clients_); 468 ClientList clients_copy(clients_);
466 for (ClientList::const_iterator client = clients_copy.begin(); 469 for (ClientList::const_iterator client = clients_copy.begin();
467 client != clients_copy.end(); client++) { 470 client != clients_copy.end(); client++) {
468 ConnectionToClient* connection_other = client->get()->connection(); 471 ConnectionToClient* connection_other = client->get()->connection();
469 if (connection_other != connection) { 472 if (connection_other != connection) {
470 OnClientDisconnected(connection_other); 473 OnClientDisconnected(connection_other);
471 } 474 }
472 } 475 }
473 // Those disconnections should have killed the screen recorder. 476 // Those disconnections should have killed the screen recorder.
474 CHECK(recorder_.get() == NULL); 477 CHECK(recorder_.get() == NULL);
475 478
476 // Create a new RecordSession if there was none. 479 // Create a new RecordSession if there was none.
477 if (!recorder_.get()) { 480 if (!recorder_.get()) {
478 // Then we create a ScreenRecorder passing the message loops that 481 // Then we create a ScreenRecorder passing the message loops that
479 // it should run on. 482 // it should run on.
480 Encoder* encoder = CreateEncoder(connection->session()->config()); 483 Encoder* encoder = CreateEncoder(config);
481 484
482 recorder_ = new ScreenRecorder(context_->main_message_loop(), 485 recorder_ = new ScreenRecorder(context_->main_message_loop(),
483 context_->encode_message_loop(), 486 context_->encode_message_loop(),
484 context_->network_message_loop(), 487 context_->network_message_loop(),
485 desktop_environment_->capturer(), 488 desktop_environment_->capturer(),
486 encoder); 489 encoder);
487 } 490 }
488 491
489 // Immediately add the connection and start the session. 492 // Immediately add the connection and start the session.
490 recorder_->AddConnection(connection); 493 recorder_->AddConnection(connection);
491 recorder_->Start(); 494 recorder_->Start();
492 // Notify observers that there is at least one authenticated client. 495 // Notify observers that there is at least one authenticated client.
493 for (StatusObserverList::iterator it = status_observers_.begin(); 496 for (StatusObserverList::iterator it = status_observers_.begin();
494 it != status_observers_.end(); ++it) { 497 it != status_observers_.end(); ++it) {
495 (*it)->OnClientAuthenticated(connection); 498 (*it)->OnClientAuthenticated(jid);
496 } 499 }
497 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, 500 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect,
498 // including closing the connection on failure of a critical operation. 501 // including closing the connection on failure of a critical operation.
499 EnableCurtainMode(true); 502 EnableCurtainMode(true);
500 if (is_it2me_) { 503 if (is_it2me_) {
501 std::string username = connection->session()->jid(); 504 std::string username = jid;
502 size_t pos = username.find('/'); 505 size_t pos = username.find('/');
503 if (pos != std::string::npos) 506 if (pos != std::string::npos)
504 username.replace(pos, std::string::npos, ""); 507 username.replace(pos, std::string::npos, "");
505 desktop_environment_->OnConnect(username); 508 desktop_environment_->OnConnect(username);
506 } 509 }
507 } 510 }
508 511
509 void ChromotingHost::LocalLoginFailed( 512 void ChromotingHost::LocalLoginFailed(
510 scoped_refptr<ConnectionToClient> connection) { 513 scoped_refptr<ConnectionToClient> connection) {
511 if (MessageLoop::current() != context_->main_message_loop()) { 514 if (MessageLoop::current() != context_->main_message_loop()) {
(...skipping 12 matching lines...) Expand all
524 void ChromotingHost::ProcessPreAuthentication( 527 void ChromotingHost::ProcessPreAuthentication(
525 const scoped_refptr<ConnectionToClient>& connection) { 528 const scoped_refptr<ConnectionToClient>& connection) {
526 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); 529 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
527 // Find the client session corresponding to the given connection. 530 // Find the client session corresponding to the given connection.
528 ClientList::iterator client; 531 ClientList::iterator client;
529 for (client = clients_.begin(); client != clients_.end(); ++client) { 532 for (client = clients_.begin(); client != clients_.end(); ++client) {
530 if (client->get()->connection() == connection) 533 if (client->get()->connection() == connection)
531 break; 534 break;
532 } 535 }
533 CHECK(client != clients_.end()); 536 CHECK(client != clients_.end());
534 client->get()->OnAuthorizationComplete(true); 537
538 context_->network_message_loop()->PostTask(
539 FROM_HERE, base::Bind(&ClientSession::OnAuthorizationComplete,
540 client->get(), true));
535 } 541 }
536 542
537 void ChromotingHost::StopScreenRecorder() { 543 void ChromotingHost::StopScreenRecorder() {
538 DCHECK(MessageLoop::current() == context_->main_message_loop()); 544 DCHECK(MessageLoop::current() == context_->main_message_loop());
539 DCHECK(recorder_.get()); 545 DCHECK(recorder_.get());
540 546
541 ++stopping_recorders_; 547 ++stopping_recorders_;
542 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); 548 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this));
543 recorder_ = NULL; 549 recorder_ = NULL;
544 } 550 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 634
629 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); 635 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin();
630 it != shutdown_tasks_.end(); ++it) { 636 it != shutdown_tasks_.end(); ++it) {
631 (*it)->Run(); 637 (*it)->Run();
632 delete *it; 638 delete *it;
633 } 639 }
634 shutdown_tasks_.clear(); 640 shutdown_tasks_.clear();
635 } 641 }
636 642
637 } // namespace remoting 643 } // 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