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

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

Issue 8495024: Access ChromotingHost::clients_ only on network thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 1 month 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
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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 ChromotingHost::ChromotingHost(ChromotingHostContext* context, 47 ChromotingHost::ChromotingHost(ChromotingHostContext* context,
48 MutableHostConfig* config, 48 MutableHostConfig* config,
49 DesktopEnvironment* environment, 49 DesktopEnvironment* environment,
50 AccessVerifier* access_verifier, 50 AccessVerifier* access_verifier,
51 bool allow_nat_traversal) 51 bool allow_nat_traversal)
52 : context_(context), 52 : context_(context),
53 desktop_environment_(environment), 53 desktop_environment_(environment),
54 config_(config), 54 config_(config),
55 access_verifier_(access_verifier), 55 access_verifier_(access_verifier),
56 allow_nat_traversal_(allow_nat_traversal), 56 allow_nat_traversal_(allow_nat_traversal),
57 stopping_recorders_(0),
57 state_(kInitial), 58 state_(kInitial),
58 stopping_recorders_(0),
59 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), 59 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()),
60 is_curtained_(false), 60 is_curtained_(false),
61 is_it2me_(false) { 61 is_it2me_(false) {
62 DCHECK(desktop_environment_); 62 DCHECK(desktop_environment_);
63 desktop_environment_->set_host(this); 63 desktop_environment_->set_host(this);
64 } 64 }
65 65
66 ChromotingHost::~ChromotingHost() { 66 ChromotingHost::~ChromotingHost() {
67 } 67 }
68 68
(...skipping 29 matching lines...) Expand all
98 98
99 signal_strategy_.reset( 99 signal_strategy_.reset(
100 new XmppSignalStrategy(context_->jingle_thread(), xmpp_login, 100 new XmppSignalStrategy(context_->jingle_thread(), xmpp_login,
101 xmpp_auth_token, 101 xmpp_auth_token,
102 xmpp_auth_service)); 102 xmpp_auth_service));
103 signal_strategy_->Init(this); 103 signal_strategy_->Init(this);
104 } 104 }
105 105
106 // This method is called when we need to destroy the host process. 106 // This method is called when we need to destroy the host process.
107 void ChromotingHost::Shutdown(Task* shutdown_task) { 107 void ChromotingHost::Shutdown(Task* shutdown_task) {
108 if (MessageLoop::current() != context_->main_message_loop()) { 108 if (!context_->network_message_loop()->BelongsToCurrentThread()) {
109 context_->main_message_loop()->PostTask( 109 context_->network_message_loop()->PostTask(
110 FROM_HERE, 110 FROM_HERE, base::Bind(&ChromotingHost::Shutdown, this, shutdown_task));
111 base::Bind(&ChromotingHost::Shutdown, this, shutdown_task));
112 return; 111 return;
113 } 112 }
114 113
115 // No-op if this object is not started yet. 114 // No-op if this object is not started yet.
116 { 115 {
117 base::AutoLock auto_lock(lock_); 116 base::AutoLock auto_lock(lock_);
118 if (state_ == kInitial || state_ == kStopped) { 117 if (state_ == kInitial || state_ == kStopped) {
119 // Nothing to do if we are not started. 118 // Nothing to do if we are not started.
120 state_ = kStopped; 119 state_ = kStopped;
121 context_->main_message_loop()->PostTask(FROM_HERE, shutdown_task); 120 context_->network_message_loop()->PostTask(FROM_HERE, shutdown_task);
122 return; 121 return;
123 } 122 }
124 if (shutdown_task) 123 if (shutdown_task)
125 shutdown_tasks_.push_back(shutdown_task); 124 shutdown_tasks_.push_back(shutdown_task);
126 if (state_ == kStopping) 125 if (state_ == kStopping)
127 return; 126 return;
128 state_ = kStopping; 127 state_ = kStopping;
129 } 128 }
130 129
131 // Disconnect all of the clients, implicitly stopping the ScreenRecorder. 130 // Disconnect all of the clients, implicitly stopping the ScreenRecorder.
132 while (!clients_.empty()) { 131 while (!clients_.empty()) {
133 scoped_refptr<ClientSession> client = clients_.front(); 132 scoped_refptr<ClientSession> client = clients_.front();
134 client->Disconnect(); 133 client->Disconnect();
135 OnClientDisconnected(client); 134 OnSessionClosed(client);
136 } 135 }
137 136
138 ShutdownNetwork(); 137 // Stop chromotocol session manager.
Wez 2011/11/09 02:32:22 nit: chromotocol -> Chromotocol.
Wez 2011/11/09 02:32:22 Clarify that we're guaranteed no more callbacks af
Sergey Ulanov 2011/11/09 21:24:00 Changed to Stop session manager.
Sergey Ulanov 2011/11/09 21:24:00 This is specified in SessionManager header. Don't
138 if (session_manager_.get()) {
139 session_manager_->Close();
140 context_->network_message_loop()->PostTask(FROM_HERE, base::Bind(
141 &DeletePointer<protocol::SessionManager>, session_manager_.release()));
Wez 2011/11/09 02:32:22 This looks like a DeleteSoon()? Clarify in the co
Sergey Ulanov 2011/11/09 21:24:00 Done.
142 }
143
144 // Stop XMPP connection.
Wez 2011/11/09 02:32:22 Clarify that this is synchronous?
Sergey Ulanov 2011/11/09 21:24:00 Done.
145 if (signal_strategy_.get()) {
146 signal_strategy_->Close();
147 signal_strategy_.reset();
148
149 for (StatusObserverList::iterator it = status_observers_.begin();
150 it != status_observers_.end(); ++it) {
151 (*it)->OnSignallingDisconnected();
152 }
153 }
154
155 if (recorder_.get()) {
156 StopScreenRecorder();
157 } else {
158 ShutdownFinish();
159 }
139 } 160 }
140 161
141 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { 162 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) {
142 DCHECK_EQ(state_, kInitial); 163 DCHECK_EQ(state_, kInitial);
143 status_observers_.push_back(observer); 164 status_observers_.push_back(observer);
144 } 165 }
145 166
146 //////////////////////////////////////////////////////////////////////////// 167 ////////////////////////////////////////////////////////////////////////////
147 // protocol::ClientSession::EventHandler implementation. 168 // protocol::ClientSession::EventHandler implementation.
148 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) { 169 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) {
149 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); 170 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
150 protocol::Session* session = client->connection()->session(); 171
151 context_->main_message_loop()->PostTask( 172 // Disconnect all other clients.
152 FROM_HERE, base::Bind(&ChromotingHost::AddAuthenticatedClient, 173 // Iterate over a copy of the list of clients, to avoid mutating the list
153 this, make_scoped_refptr(client), 174 // while iterating over it.
154 session->config(), session->jid())); 175 ClientList clients_copy(clients_);
176 for (ClientList::const_iterator other_client = clients_copy.begin();
177 other_client != clients_copy.end(); ++other_client) {
178 if ((*other_client) != client) {
179 (*other_client)->Disconnect();
180 OnSessionClosed(*other_client);
Wez 2011/11/09 02:32:22 If Disconnect() is made to trigger OnSessionClosed
Sergey Ulanov 2011/11/09 21:24:00 I don't think that Disconnect() should trigger OnS
Wez 2011/11/09 23:18:45 Why not? The EventHandler really only cares that
Sergey Ulanov 2011/11/10 21:06:14 Ok. I've changed Disconnect() to trigger OnSession
181 }
182 }
183
184 // Those disconnections should have killed the screen recorder.
185 CHECK(recorder_.get() == NULL);
Wez 2011/11/09 02:32:22 We're in OnSessionAuthenticated(), so surely this
Sergey Ulanov 2011/11/09 21:24:00 Recorder is created after client is authenticated,
Wez 2011/11/09 23:18:45 But by the time we reach here the client we're add
Sergey Ulanov 2011/11/10 21:06:14 I see your point now. Removed this CHECK because i
186
187 // Create a new RecordSession if there was none.
188 if (!recorder_.get()) {
189 // Then we create a ScreenRecorder passing the message loops that
190 // it should run on.
191 Encoder* encoder = CreateEncoder(client->connection()->session()->config());
192
193 recorder_ = new ScreenRecorder(context_->main_message_loop(),
194 context_->encode_message_loop(),
195 context_->network_message_loop(),
196 desktop_environment_->capturer(),
197 encoder);
198 }
199
200 // Immediately add the connection and start the session.
201 recorder_->AddConnection(client->connection());
202 recorder_->Start();
203
204 const std::string& jid = client->connection()->session()->jid();
Wez 2011/11/09 02:32:22 nit: Move this after the Notify observers comment?
Sergey Ulanov 2011/11/09 21:24:00 Done.
205
206 // Notify observers that there is at least one authenticated client.
207 for (StatusObserverList::iterator it = status_observers_.begin();
208 it != status_observers_.end(); ++it) {
209 (*it)->OnClientAuthenticated(jid);
210 }
211 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect,
212 // including closing the connection on failure of a critical operation.
213 EnableCurtainMode(true);
214
215 std::string username = jid;
Wez 2011/11/09 02:32:22 Why not just take a copy of the JID in the first p
Sergey Ulanov 2011/11/09 21:24:00 Simplified this code to use substr().
216 size_t pos = username.find('/');
217 if (pos != std::string::npos)
218 username.erase(pos);
219 desktop_environment_->OnConnect(username);
155 } 220 }
156 221
157 void ChromotingHost::OnSessionClosed(ClientSession* client) { 222 void ChromotingHost::OnSessionClosed(ClientSession* client) {
158 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); 223 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
159 224
160 VLOG(1) << "Connection to client closed."; 225 scoped_refptr<ClientSession> client_ref = client;
161 context_->main_message_loop()->PostTask( 226
162 FROM_HERE, base::Bind(&ChromotingHost::OnClientDisconnected, this, 227 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client);
163 make_scoped_refptr(client))); 228 CHECK(it != clients_.end());
229 clients_.erase(it);
230
231 if (recorder_.get()) {
232 recorder_->RemoveConnection(client->connection());
233 }
234
235 for (StatusObserverList::iterator it = status_observers_.begin();
236 it != status_observers_.end(); ++it) {
237 (*it)->OnClientDisconnected(client->client_jid());
238 }
239
240 if (AuthenticatedClientsCount() == 0) {
241 if (recorder_.get()) {
242 // Stop the recorder if there are no more clients.
243 StopScreenRecorder();
244 }
245
246 // Disable the "curtain" if there are no more active clients.
247 EnableCurtainMode(false);
248 desktop_environment_->OnLastDisconnect();
249 }
164 } 250 }
165 251
166 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session, 252 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session,
167 int64 sequence_number) { 253 int64 sequence_number) {
168 // Update the sequence number in ScreenRecorder. 254 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
169 if (MessageLoop::current() != context_->main_message_loop()) {
170 context_->main_message_loop()->PostTask(
171 FROM_HERE, base::Bind(&ChromotingHost::OnSessionSequenceNumber, this,
172 make_scoped_refptr(session), sequence_number));
173 return;
174 }
175
176 if (recorder_.get()) 255 if (recorder_.get())
177 recorder_->UpdateSequenceNumber(sequence_number); 256 recorder_->UpdateSequenceNumber(sequence_number);
178 } 257 }
179 258
180 //////////////////////////////////////////////////////////////////////////// 259 ////////////////////////////////////////////////////////////////////////////
181 // SignalStrategy::StatusObserver implementations 260 // SignalStrategy::StatusObserver implementations
182 void ChromotingHost::OnStateChange( 261 void ChromotingHost::OnStateChange(
183 SignalStrategy::StatusObserver::State state) { 262 SignalStrategy::StatusObserver::State state) {
184 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); 263 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
185 264
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 363
285 *response = protocol::SessionManager::ACCEPT; 364 *response = protocol::SessionManager::ACCEPT;
286 365
287 LOG(INFO) << "Client connected: " << session->jid(); 366 LOG(INFO) << "Client connected: " << session->jid();
288 367
289 // Create a client object. 368 // Create a client object.
290 scoped_refptr<protocol::ConnectionToClient> connection = 369 scoped_refptr<protocol::ConnectionToClient> connection =
291 new protocol::ConnectionToClient(context_->network_message_loop(), 370 new protocol::ConnectionToClient(context_->network_message_loop(),
292 session); 371 session);
293 ClientSession* client = new ClientSession( 372 ClientSession* client = new ClientSession(
294 this, connection, 373 this, connection, desktop_environment_->event_executor(),
295 desktop_environment_->event_executor(),
296 desktop_environment_->capturer()); 374 desktop_environment_->capturer());
297
298 clients_.push_back(client); 375 clients_.push_back(client);
299 } 376 }
300 377
301 void ChromotingHost::set_protocol_config( 378 void ChromotingHost::set_protocol_config(
302 protocol::CandidateSessionConfig* config) { 379 protocol::CandidateSessionConfig* config) {
303 DCHECK(config_.get()); 380 DCHECK(config_.get());
304 DCHECK_EQ(state_, kInitial); 381 DCHECK_EQ(state_, kInitial);
305 protocol_config_.reset(config); 382 protocol_config_.reset(config);
Wez 2011/11/09 02:32:22 Not part of this CL, but this is client-specific,
Sergey Ulanov 2011/11/09 21:24:00 Actually it is not client-specific - this sets Can
306 } 383 }
307 384
308 void ChromotingHost::LocalMouseMoved(const SkIPoint& new_pos) { 385 void ChromotingHost::LocalMouseMoved(const SkIPoint& new_pos) {
309 if (!context_->network_message_loop()->BelongsToCurrentThread()) { 386 if (!context_->network_message_loop()->BelongsToCurrentThread()) {
310 context_->network_message_loop()->PostTask( 387 context_->network_message_loop()->PostTask(
311 FROM_HERE, base::Bind(&ChromotingHost::LocalMouseMoved, this, new_pos)); 388 FROM_HERE, base::Bind(&ChromotingHost::LocalMouseMoved, this, new_pos));
312 return; 389 return;
313 } 390 }
391
314 ClientList::iterator client; 392 ClientList::iterator client;
315 for (client = clients_.begin(); client != clients_.end(); ++client) { 393 for (client = clients_.begin(); client != clients_.end(); ++client) {
316 client->get()->LocalMouseMoved(new_pos); 394 client->get()->LocalMouseMoved(new_pos);
317 } 395 }
318 } 396 }
319 397
320 void ChromotingHost::PauseSession(bool pause) { 398 void ChromotingHost::PauseSession(bool pause) {
321 if (context_->main_message_loop() != MessageLoop::current()) { 399 if (!context_->network_message_loop()->BelongsToCurrentThread()) {
322 context_->main_message_loop()->PostTask( 400 context_->network_message_loop()->PostTask(
323 FROM_HERE, 401 FROM_HERE,
324 NewRunnableMethod(this, 402 NewRunnableMethod(this,
325 &ChromotingHost::PauseSession, 403 &ChromotingHost::PauseSession,
326 pause)); 404 pause));
327 return; 405 return;
328 } 406 }
407
329 ClientList::iterator client; 408 ClientList::iterator client;
330 for (client = clients_.begin(); client != clients_.end(); ++client) { 409 for (client = clients_.begin(); client != clients_.end(); ++client) {
331 client->get()->set_awaiting_continue_approval(pause); 410 client->get()->set_awaiting_continue_approval(pause);
332 } 411 }
333 desktop_environment_->OnPause(pause); 412 desktop_environment_->OnPause(pause);
Wez 2011/11/09 02:32:22 Is this callable on the network thread?
Sergey Ulanov 2011/11/09 21:24:00 Yes. All DesktopEnvironment methods can be called
334 } 413 }
335 414
336 void ChromotingHost::SetUiStrings(const UiStrings& ui_strings) { 415 void ChromotingHost::SetUiStrings(const UiStrings& ui_strings) {
337 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); 416 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
338 DCHECK_EQ(state_, kInitial); 417 DCHECK_EQ(state_, kInitial);
339 418
340 ui_strings_ = ui_strings; 419 ui_strings_ = ui_strings;
341 } 420 }
342 421
343 void ChromotingHost::OnClientDisconnected(ClientSession* client) {
344 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
345
346 scoped_refptr<ClientSession> client_ref = client;
347
348 ClientList::iterator it;
349 for (it = clients_.begin(); it != clients_.end(); ++it) {
350 if (it->get() == client)
351 break;
352 }
353 clients_.erase(it);
354
355 if (recorder_.get()) {
356 recorder_->RemoveConnection(client->connection());
357 }
358
359 for (StatusObserverList::iterator it = status_observers_.begin();
360 it != status_observers_.end(); ++it) {
361 (*it)->OnClientDisconnected(client->client_jid());
362 }
363
364 if (AuthenticatedClientsCount() == 0) {
365 if (recorder_.get()) {
366 // Stop the recorder if there are no more clients.
367 StopScreenRecorder();
368 }
369
370 // Disable the "curtain" if there are no more active clients.
371 EnableCurtainMode(false);
372 desktop_environment_->OnLastDisconnect();
373 }
374 }
375
376 // TODO(sergeyu): Move this to SessionManager? 422 // TODO(sergeyu): Move this to SessionManager?
377 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { 423 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) {
378 const protocol::ChannelConfig& video_config = config.video_config(); 424 const protocol::ChannelConfig& video_config = config.video_config();
379 425
380 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { 426 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
381 return EncoderRowBased::CreateVerbatimEncoder(); 427 return EncoderRowBased::CreateVerbatimEncoder();
382 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) { 428 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) {
383 return EncoderRowBased::CreateZlibEncoder(); 429 return EncoderRowBased::CreateZlibEncoder();
384 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) { 430 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) {
385 return new remoting::EncoderVp8(); 431 return new remoting::EncoderVp8();
386 } 432 }
387 433
388 return NULL; 434 return NULL;
389 } 435 }
390 436
391 std::string ChromotingHost::GenerateHostAuthToken( 437 std::string ChromotingHost::GenerateHostAuthToken(
392 const std::string& encoded_client_token) { 438 const std::string& encoded_client_token) {
393 // TODO(ajwong): Return the signature of this instead. 439 // TODO(ajwong): Return the signature of this instead.
394 return encoded_client_token; 440 return encoded_client_token;
395 } 441 }
396 442
397 int ChromotingHost::AuthenticatedClientsCount() const { 443 int ChromotingHost::AuthenticatedClientsCount() const {
444 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
445
398 int authenticated_clients = 0; 446 int authenticated_clients = 0;
399 for (ClientList::const_iterator it = clients_.begin(); it != clients_.end(); 447 for (ClientList::const_iterator it = clients_.begin(); it != clients_.end();
400 ++it) { 448 ++it) {
401 if (it->get()->authenticated()) 449 if (it->get()->authenticated())
402 ++authenticated_clients; 450 ++authenticated_clients;
403 } 451 }
404 return authenticated_clients; 452 return authenticated_clients;
405 } 453 }
406 454
407 void ChromotingHost::EnableCurtainMode(bool enable) { 455 void ChromotingHost::EnableCurtainMode(bool enable) {
408 // TODO(jamiewalch): This will need to be more sophisticated when we think 456 // TODO(jamiewalch): This will need to be more sophisticated when we think
409 // about proper crash recovery and daemon mode. 457 // about proper crash recovery and daemon mode.
410 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. 458 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost.
411 if (is_it2me_ || enable == is_curtained_) 459 if (is_it2me_ || enable == is_curtained_)
412 return; 460 return;
413 desktop_environment_->curtain()->EnableCurtainMode(enable); 461 desktop_environment_->curtain()->EnableCurtainMode(enable);
414 is_curtained_ = enable; 462 is_curtained_ = enable;
415 } 463 }
416 464
417 void ChromotingHost::AddAuthenticatedClient(
418 ClientSession* client,
419 const protocol::SessionConfig& config,
420 const std::string& jid) {
421 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
422
423 // Disconnect all other clients.
424 // Iterate over a copy of the list of clients, to avoid mutating the list
425 // while iterating over it.
426 ClientList clients_copy(clients_);
427 for (ClientList::const_iterator other_client = clients_copy.begin();
428 other_client != clients_copy.end(); ++other_client) {
429 if ((*other_client) != client) {
430 (*other_client)->Disconnect();
431 OnClientDisconnected(*other_client);
432 }
433 }
434
435 // Those disconnections should have killed the screen recorder.
436 CHECK(recorder_.get() == NULL);
437
438 // Create a new RecordSession if there was none.
439 if (!recorder_.get()) {
440 // Then we create a ScreenRecorder passing the message loops that
441 // it should run on.
442 Encoder* encoder = CreateEncoder(config);
443
444 recorder_ = new ScreenRecorder(context_->main_message_loop(),
445 context_->encode_message_loop(),
446 context_->network_message_loop(),
447 desktop_environment_->capturer(),
448 encoder);
449 }
450
451 // Immediately add the connection and start the session.
452 recorder_->AddConnection(client->connection());
453 recorder_->Start();
454 // Notify observers that there is at least one authenticated client.
455 for (StatusObserverList::iterator it = status_observers_.begin();
456 it != status_observers_.end(); ++it) {
457 (*it)->OnClientAuthenticated(jid);
458 }
459 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect,
460 // including closing the connection on failure of a critical operation.
461 EnableCurtainMode(true);
462 if (is_it2me_) {
463 std::string username = jid;
464 size_t pos = username.find('/');
465 if (pos != std::string::npos)
466 username.replace(pos, std::string::npos, "");
467 desktop_environment_->OnConnect(username);
468 }
469 }
470
471 void ChromotingHost::StopScreenRecorder() { 465 void ChromotingHost::StopScreenRecorder() {
472 DCHECK(MessageLoop::current() == context_->main_message_loop()); 466 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
473 DCHECK(recorder_.get()); 467 DCHECK(recorder_.get());
474 468
475 ++stopping_recorders_; 469 ++stopping_recorders_;
476 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); 470 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this));
477 recorder_ = NULL; 471 recorder_ = NULL;
Wez 2011/11/09 02:32:22 Does ScreenRecorder::Stop() guarantee to NOT invok
Sergey Ulanov 2011/11/09 21:24:00 Good catch. Fixed, though it should not be a probl
478 } 472 }
479 473
480 void ChromotingHost::OnScreenRecorderStopped() { 474 void ChromotingHost::OnScreenRecorderStopped() {
481 if (MessageLoop::current() != context_->main_message_loop()) { 475 if (!context_->network_message_loop()->BelongsToCurrentThread()) {
482 context_->main_message_loop()->PostTask( 476 context_->network_message_loop()->PostTask(
483 FROM_HERE, base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); 477 FROM_HERE, base::Bind(&ChromotingHost::OnScreenRecorderStopped, this));
484 return; 478 return;
485 } 479 }
486 480
487 --stopping_recorders_; 481 --stopping_recorders_;
488 DCHECK_GE(stopping_recorders_, 0); 482 DCHECK_GE(stopping_recorders_, 0);
489 483
490 bool stopping; 484 bool stopping;
491 { 485 {
492 base::AutoLock auto_lock(lock_); 486 base::AutoLock auto_lock(lock_);
493 stopping = state_ == kStopping; 487 stopping = state_ == kStopping;
494 } 488 }
495 489
496 if (!stopping_recorders_ && stopping) 490 if (!stopping_recorders_ && stopping)
497 ShutdownFinish(); 491 ShutdownFinish();
498 } 492 }
499 493
500 void ChromotingHost::ShutdownNetwork() {
501 if (!context_->network_message_loop()->BelongsToCurrentThread()) {
502 context_->network_message_loop()->PostTask(
503 FROM_HERE, base::Bind(&ChromotingHost::ShutdownNetwork, this));
504 return;
505 }
506
507 // Stop chromotocol session manager.
508 if (session_manager_.get()) {
509 session_manager_->Close();
510 session_manager_.reset();
511 }
512
513 // Stop XMPP connection.
514 if (signal_strategy_.get()) {
515 signal_strategy_->Close();
516 signal_strategy_.reset();
517
518 for (StatusObserverList::iterator it = status_observers_.begin();
519 it != status_observers_.end(); ++it) {
520 (*it)->OnSignallingDisconnected();
521 }
522 }
523
524 ShutdownRecorder();
525 }
526
527 void ChromotingHost::ShutdownRecorder() {
528 if (MessageLoop::current() != context_->main_message_loop()) {
529 context_->main_message_loop()->PostTask(
530 FROM_HERE, base::Bind(&ChromotingHost::ShutdownRecorder, this));
531 return;
532 }
533
534 if (recorder_.get()) {
535 StopScreenRecorder();
536 } else if (!stopping_recorders_) {
537 ShutdownFinish();
538 }
539 }
540
541 void ChromotingHost::ShutdownFinish() { 494 void ChromotingHost::ShutdownFinish() {
542 if (MessageLoop::current() != context_->main_message_loop()) { 495 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
543 context_->main_message_loop()->PostTask(
544 FROM_HERE, base::Bind(&ChromotingHost::ShutdownFinish, this));
545 return;
546 }
547 496
548 { 497 {
549 base::AutoLock auto_lock(lock_); 498 base::AutoLock auto_lock(lock_);
550 state_ = kStopped; 499 state_ = kStopped;
551 } 500 }
552 501
553 // Keep reference to |this|, so that we don't get destroyed while 502 // Keep reference to |this|, so that we don't get destroyed while
554 // sending notifications. 503 // sending notifications.
555 scoped_refptr<ChromotingHost> self(this); 504 scoped_refptr<ChromotingHost> self(this);
556 505
557 // Notify observers. 506 // Notify observers.
558 for (StatusObserverList::iterator it = status_observers_.begin(); 507 for (StatusObserverList::iterator it = status_observers_.begin();
559 it != status_observers_.end(); ++it) { 508 it != status_observers_.end(); ++it) {
560 (*it)->OnShutdown(); 509 (*it)->OnShutdown();
Wez 2011/11/09 02:32:22 We're notifying observers on a different thread to
Sergey Ulanov 2011/11/09 21:24:00 There is only one observer that cares about this e
561 } 510 }
562 511
563 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); 512 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin();
564 it != shutdown_tasks_.end(); ++it) { 513 it != shutdown_tasks_.end(); ++it) {
565 (*it)->Run(); 514 (*it)->Run();
566 delete *it; 515 delete *it;
567 } 516 }
568 shutdown_tasks_.clear(); 517 shutdown_tasks_.clear();
569 } 518 }
570 519
520
571 } // namespace remoting 521 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698