OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 signal_strategy_(signal_strategy), | 70 signal_strategy_(signal_strategy), |
71 stopping_recorders_(0), | 71 stopping_recorders_(0), |
72 state_(kInitial), | 72 state_(kInitial), |
73 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), | 73 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), |
74 login_backoff_(&kDefaultBackoffPolicy), | 74 login_backoff_(&kDefaultBackoffPolicy), |
75 authenticating_client_(false), | 75 authenticating_client_(false), |
76 reject_authenticating_client_(false) { | 76 reject_authenticating_client_(false) { |
77 DCHECK(context_); | 77 DCHECK(context_); |
78 DCHECK(signal_strategy); | 78 DCHECK(signal_strategy); |
79 DCHECK(desktop_environment_); | 79 DCHECK(desktop_environment_); |
80 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 80 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
81 } | 81 } |
82 | 82 |
83 ChromotingHost::~ChromotingHost() { | 83 ChromotingHost::~ChromotingHost() { |
84 DCHECK(clients_.empty()); | 84 DCHECK(clients_.empty()); |
85 } | 85 } |
86 | 86 |
87 void ChromotingHost::Start() { | 87 void ChromotingHost::Start() { |
88 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 88 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
89 | 89 |
90 LOG(INFO) << "Starting host"; | 90 LOG(INFO) << "Starting host"; |
91 | 91 |
92 // Make sure this object is not started. | 92 // Make sure this object is not started. |
93 if (state_ != kInitial) | 93 if (state_ != kInitial) |
94 return; | 94 return; |
95 state_ = kStarted; | 95 state_ = kStarted; |
96 | 96 |
97 // Start the SessionManager, supplying this ChromotingHost as the listener. | 97 // Start the SessionManager, supplying this ChromotingHost as the listener. |
98 session_manager_->Init(signal_strategy_, this); | 98 session_manager_->Init(signal_strategy_, this); |
99 } | 99 } |
100 | 100 |
101 // This method is called when we need to destroy the host process. | 101 // This method is called when we need to destroy the host process. |
102 void ChromotingHost::Shutdown(const base::Closure& shutdown_task) { | 102 void ChromotingHost::Shutdown(const base::Closure& shutdown_task) { |
103 if (!context_->network_message_loop()->BelongsToCurrentThread()) { | 103 if (!context_->network_task_runner()->BelongsToCurrentThread()) { |
104 context_->network_message_loop()->PostTask( | 104 context_->network_task_runner()->PostTask( |
105 FROM_HERE, base::Bind(&ChromotingHost::Shutdown, this, shutdown_task)); | 105 FROM_HERE, base::Bind(&ChromotingHost::Shutdown, this, shutdown_task)); |
106 return; | 106 return; |
107 } | 107 } |
108 | 108 |
109 // No-op if this object is not started yet. | 109 // No-op if this object is not started yet. |
110 if (state_ == kInitial || state_ == kStopped) { | 110 if (state_ == kInitial || state_ == kStopped) { |
111 // Nothing to do if we are not started. | 111 // Nothing to do if we are not started. |
112 state_ = kStopped; | 112 state_ = kStopped; |
113 context_->network_message_loop()->PostTask(FROM_HERE, shutdown_task); | 113 context_->network_task_runner()->PostTask(FROM_HERE, shutdown_task); |
114 return; | 114 return; |
115 } | 115 } |
116 if (!shutdown_task.is_null()) | 116 if (!shutdown_task.is_null()) |
117 shutdown_tasks_.push_back(shutdown_task); | 117 shutdown_tasks_.push_back(shutdown_task); |
118 if (state_ == kStopping) | 118 if (state_ == kStopping) |
119 return; | 119 return; |
120 state_ = kStopping; | 120 state_ = kStopping; |
121 | 121 |
122 // Disconnect all of the clients, implicitly stopping the ScreenRecorder. | 122 // Disconnect all of the clients, implicitly stopping the ScreenRecorder. |
123 while (!clients_.empty()) { | 123 while (!clients_.empty()) { |
124 clients_.front()->Disconnect(); | 124 clients_.front()->Disconnect(); |
125 } | 125 } |
126 | 126 |
127 // Destroy session manager. | 127 // Destroy session manager. |
128 session_manager_.reset(); | 128 session_manager_.reset(); |
129 | 129 |
130 // Stop screen recorder | 130 // Stop screen recorder |
131 if (recorder_.get()) { | 131 if (recorder_.get()) { |
132 StopScreenRecorder(); | 132 StopScreenRecorder(); |
133 } else if (!stopping_recorders_) { | 133 } else if (!stopping_recorders_) { |
134 ShutdownFinish(); | 134 ShutdownFinish(); |
135 } | 135 } |
136 } | 136 } |
137 | 137 |
138 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { | 138 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { |
139 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 139 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
140 status_observers_.AddObserver(observer); | 140 status_observers_.AddObserver(observer); |
141 } | 141 } |
142 | 142 |
143 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) { | 143 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) { |
144 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 144 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
145 status_observers_.RemoveObserver(observer); | 145 status_observers_.RemoveObserver(observer); |
146 } | 146 } |
147 | 147 |
148 void ChromotingHost::RejectAuthenticatingClient() { | 148 void ChromotingHost::RejectAuthenticatingClient() { |
149 DCHECK(authenticating_client_); | 149 DCHECK(authenticating_client_); |
150 reject_authenticating_client_ = true; | 150 reject_authenticating_client_ = true; |
151 } | 151 } |
152 | 152 |
153 void ChromotingHost::SetAuthenticatorFactory( | 153 void ChromotingHost::SetAuthenticatorFactory( |
154 scoped_ptr<protocol::AuthenticatorFactory> authenticator_factory) { | 154 scoped_ptr<protocol::AuthenticatorFactory> authenticator_factory) { |
155 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 155 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
156 session_manager_->set_authenticator_factory(authenticator_factory.Pass()); | 156 session_manager_->set_authenticator_factory(authenticator_factory.Pass()); |
157 } | 157 } |
158 | 158 |
159 //////////////////////////////////////////////////////////////////////////// | 159 //////////////////////////////////////////////////////////////////////////// |
160 // protocol::ClientSession::EventHandler implementation. | 160 // protocol::ClientSession::EventHandler implementation. |
161 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) { | 161 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) { |
162 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 162 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
163 | 163 |
164 login_backoff_.Reset(); | 164 login_backoff_.Reset(); |
165 | 165 |
166 // Disconnect all other clients. | 166 // Disconnect all other clients. |
167 // Iterate over a copy of the list of clients, to avoid mutating the list | 167 // Iterate over a copy of the list of clients, to avoid mutating the list |
168 // while iterating over it. | 168 // while iterating over it. |
169 ClientList clients_copy(clients_); | 169 ClientList clients_copy(clients_); |
170 for (ClientList::const_iterator other_client = clients_copy.begin(); | 170 for (ClientList::const_iterator other_client = clients_copy.begin(); |
171 other_client != clients_copy.end(); ++other_client) { | 171 other_client != clients_copy.end(); ++other_client) { |
172 if ((*other_client) != client) { | 172 if ((*other_client) != client) { |
(...skipping 14 matching lines...) Expand all Loading... |
187 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 187 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
188 OnClientAuthenticated(jid)); | 188 OnClientAuthenticated(jid)); |
189 authenticating_client_ = false; | 189 authenticating_client_ = false; |
190 | 190 |
191 if (reject_authenticating_client_) { | 191 if (reject_authenticating_client_) { |
192 client->Disconnect(); | 192 client->Disconnect(); |
193 } | 193 } |
194 } | 194 } |
195 | 195 |
196 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) { | 196 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) { |
197 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 197 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
198 | 198 |
199 // Then we create a ScreenRecorder passing the message loops that | 199 // Then we create a ScreenRecorder passing the message loops that |
200 // it should run on. | 200 // it should run on. |
201 Encoder* encoder = CreateEncoder(client->connection()->session()->config()); | 201 Encoder* encoder = CreateEncoder(client->connection()->session()->config()); |
202 | 202 |
203 recorder_ = new ScreenRecorder(context_->main_message_loop(), | 203 recorder_ = new ScreenRecorder(context_->main_task_runner(), |
204 context_->encode_message_loop(), | 204 context_->encode_task_runner(), |
205 context_->network_message_loop(), | 205 context_->network_task_runner(), |
206 desktop_environment_->capturer(), | 206 desktop_environment_->capturer(), |
207 encoder); | 207 encoder); |
208 | 208 |
209 // Immediately add the connection and start the session. | 209 // Immediately add the connection and start the session. |
210 recorder_->AddConnection(client->connection()); | 210 recorder_->AddConnection(client->connection()); |
211 recorder_->Start(); | 211 recorder_->Start(); |
212 desktop_environment_->OnSessionStarted(client->CreateClipboardProxy()); | 212 desktop_environment_->OnSessionStarted(client->CreateClipboardProxy()); |
213 | 213 |
214 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 214 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
215 OnClientConnected(client->client_jid())); | 215 OnClientConnected(client->client_jid())); |
216 } | 216 } |
217 | 217 |
218 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) { | 218 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) { |
219 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 219 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
220 | 220 |
221 // Notify observers. | 221 // Notify observers. |
222 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 222 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
223 OnAccessDenied(client->client_jid())); | 223 OnAccessDenied(client->client_jid())); |
224 } | 224 } |
225 | 225 |
226 void ChromotingHost::OnSessionClosed(ClientSession* client) { | 226 void ChromotingHost::OnSessionClosed(ClientSession* client) { |
227 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 227 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
228 | 228 |
229 scoped_ptr<ClientSession> client_destroyer(client); | 229 scoped_ptr<ClientSession> client_destroyer(client); |
230 | 230 |
231 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client); | 231 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client); |
232 CHECK(it != clients_.end()); | 232 CHECK(it != clients_.end()); |
233 clients_.erase(it); | 233 clients_.erase(it); |
234 | 234 |
235 if (recorder_.get()) { | 235 if (recorder_.get()) { |
236 recorder_->RemoveConnection(client->connection()); | 236 recorder_->RemoveConnection(client->connection()); |
237 } | 237 } |
238 | 238 |
239 if (client->is_authenticated()) { | 239 if (client->is_authenticated()) { |
240 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 240 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
241 OnClientDisconnected(client->client_jid())); | 241 OnClientDisconnected(client->client_jid())); |
242 | 242 |
243 // TODO(sergeyu): This teardown logic belongs to ClientSession | 243 // TODO(sergeyu): This teardown logic belongs to ClientSession |
244 // class. It should start/stop screen recorder or tell the host | 244 // class. It should start/stop screen recorder or tell the host |
245 // when to do it. | 245 // when to do it. |
246 if (recorder_.get()) { | 246 if (recorder_.get()) { |
247 // Currently we don't allow more than one simultaneous connection, | 247 // Currently we don't allow more than one simultaneous connection, |
248 // so we need to shutdown recorder when a client disconnects. | 248 // so we need to shutdown recorder when a client disconnects. |
249 StopScreenRecorder(); | 249 StopScreenRecorder(); |
250 } | 250 } |
251 desktop_environment_->OnSessionFinished(); | 251 desktop_environment_->OnSessionFinished(); |
252 } | 252 } |
253 } | 253 } |
254 | 254 |
255 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session, | 255 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session, |
256 int64 sequence_number) { | 256 int64 sequence_number) { |
257 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 257 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
258 if (recorder_.get()) | 258 if (recorder_.get()) |
259 recorder_->UpdateSequenceNumber(sequence_number); | 259 recorder_->UpdateSequenceNumber(sequence_number); |
260 } | 260 } |
261 | 261 |
262 void ChromotingHost::OnSessionRouteChange( | 262 void ChromotingHost::OnSessionRouteChange( |
263 ClientSession* session, | 263 ClientSession* session, |
264 const std::string& channel_name, | 264 const std::string& channel_name, |
265 const protocol::TransportRoute& route) { | 265 const protocol::TransportRoute& route) { |
266 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 266 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
267 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 267 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
268 OnClientRouteChange(session->client_jid(), channel_name, | 268 OnClientRouteChange(session->client_jid(), channel_name, |
269 route)); | 269 route)); |
270 } | 270 } |
271 | 271 |
272 void ChromotingHost::OnSessionManagerReady() { | 272 void ChromotingHost::OnSessionManagerReady() { |
273 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 273 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
274 // Don't need to do anything here, just wait for incoming | 274 // Don't need to do anything here, just wait for incoming |
275 // connections. | 275 // connections. |
276 } | 276 } |
277 | 277 |
278 void ChromotingHost::OnIncomingSession( | 278 void ChromotingHost::OnIncomingSession( |
279 protocol::Session* session, | 279 protocol::Session* session, |
280 protocol::SessionManager::IncomingSessionResponse* response) { | 280 protocol::SessionManager::IncomingSessionResponse* response) { |
281 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 281 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
282 | 282 |
283 if (state_ != kStarted) { | 283 if (state_ != kStarted) { |
284 *response = protocol::SessionManager::DECLINE; | 284 *response = protocol::SessionManager::DECLINE; |
285 return; | 285 return; |
286 } | 286 } |
287 | 287 |
288 if (login_backoff_.ShouldRejectRequest()) { | 288 if (login_backoff_.ShouldRejectRequest()) { |
289 *response = protocol::SessionManager::OVERLOAD; | 289 *response = protocol::SessionManager::OVERLOAD; |
290 return; | 290 return; |
291 } | 291 } |
(...skipping 22 matching lines...) Expand all Loading... |
314 scoped_ptr<protocol::ConnectionToClient> connection( | 314 scoped_ptr<protocol::ConnectionToClient> connection( |
315 new protocol::ConnectionToClient(session)); | 315 new protocol::ConnectionToClient(session)); |
316 ClientSession* client = new ClientSession( | 316 ClientSession* client = new ClientSession( |
317 this, connection.Pass(), desktop_environment_->event_executor(), | 317 this, connection.Pass(), desktop_environment_->event_executor(), |
318 desktop_environment_->capturer()); | 318 desktop_environment_->capturer()); |
319 clients_.push_back(client); | 319 clients_.push_back(client); |
320 } | 320 } |
321 | 321 |
322 void ChromotingHost::set_protocol_config( | 322 void ChromotingHost::set_protocol_config( |
323 protocol::CandidateSessionConfig* config) { | 323 protocol::CandidateSessionConfig* config) { |
324 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 324 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
325 DCHECK(config); | 325 DCHECK(config); |
326 DCHECK_EQ(state_, kInitial); | 326 DCHECK_EQ(state_, kInitial); |
327 protocol_config_.reset(config); | 327 protocol_config_.reset(config); |
328 } | 328 } |
329 | 329 |
330 void ChromotingHost::OnLocalMouseMoved(const SkIPoint& new_pos) { | 330 void ChromotingHost::OnLocalMouseMoved(const SkIPoint& new_pos) { |
331 if (!context_->network_message_loop()->BelongsToCurrentThread()) { | 331 if (!context_->network_task_runner()->BelongsToCurrentThread()) { |
332 context_->network_message_loop()->PostTask( | 332 context_->network_task_runner()->PostTask( |
333 FROM_HERE, base::Bind(&ChromotingHost::OnLocalMouseMoved, | 333 FROM_HERE, base::Bind(&ChromotingHost::OnLocalMouseMoved, |
334 this, new_pos)); | 334 this, new_pos)); |
335 return; | 335 return; |
336 } | 336 } |
337 | 337 |
338 ClientList::iterator client; | 338 ClientList::iterator client; |
339 for (client = clients_.begin(); client != clients_.end(); ++client) { | 339 for (client = clients_.begin(); client != clients_.end(); ++client) { |
340 (*client)->LocalMouseMoved(new_pos); | 340 (*client)->LocalMouseMoved(new_pos); |
341 } | 341 } |
342 } | 342 } |
343 | 343 |
344 void ChromotingHost::PauseSession(bool pause) { | 344 void ChromotingHost::PauseSession(bool pause) { |
345 if (!context_->network_message_loop()->BelongsToCurrentThread()) { | 345 if (!context_->network_task_runner()->BelongsToCurrentThread()) { |
346 context_->network_message_loop()->PostTask( | 346 context_->network_task_runner()->PostTask( |
347 FROM_HERE, base::Bind(&ChromotingHost::PauseSession, this, pause)); | 347 FROM_HERE, base::Bind(&ChromotingHost::PauseSession, this, pause)); |
348 return; | 348 return; |
349 } | 349 } |
350 | 350 |
351 ClientList::iterator client; | 351 ClientList::iterator client; |
352 for (client = clients_.begin(); client != clients_.end(); ++client) { | 352 for (client = clients_.begin(); client != clients_.end(); ++client) { |
353 (*client)->SetDisableInputs(pause); | 353 (*client)->SetDisableInputs(pause); |
354 } | 354 } |
355 } | 355 } |
356 | 356 |
357 void ChromotingHost::DisconnectAllClients() { | 357 void ChromotingHost::DisconnectAllClients() { |
358 if (!context_->network_message_loop()->BelongsToCurrentThread()) { | 358 if (!context_->network_task_runner()->BelongsToCurrentThread()) { |
359 context_->network_message_loop()->PostTask( | 359 context_->network_task_runner()->PostTask( |
360 FROM_HERE, base::Bind(&ChromotingHost::DisconnectAllClients, this)); | 360 FROM_HERE, base::Bind(&ChromotingHost::DisconnectAllClients, this)); |
361 return; | 361 return; |
362 } | 362 } |
363 | 363 |
364 while (!clients_.empty()) { | 364 while (!clients_.empty()) { |
365 size_t size = clients_.size(); | 365 size_t size = clients_.size(); |
366 clients_.front()->Disconnect(); | 366 clients_.front()->Disconnect(); |
367 CHECK_EQ(clients_.size(), size - 1); | 367 CHECK_EQ(clients_.size(), size - 1); |
368 } | 368 } |
369 } | 369 } |
370 | 370 |
371 void ChromotingHost::SetUiStrings(const UiStrings& ui_strings) { | 371 void ChromotingHost::SetUiStrings(const UiStrings& ui_strings) { |
372 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 372 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
373 DCHECK_EQ(state_, kInitial); | 373 DCHECK_EQ(state_, kInitial); |
374 | 374 |
375 ui_strings_ = ui_strings; | 375 ui_strings_ = ui_strings; |
376 } | 376 } |
377 | 377 |
378 // TODO(sergeyu): Move this to SessionManager? | 378 // TODO(sergeyu): Move this to SessionManager? |
379 // static | 379 // static |
380 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { | 380 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { |
381 const protocol::ChannelConfig& video_config = config.video_config(); | 381 const protocol::ChannelConfig& video_config = config.video_config(); |
382 | 382 |
383 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { | 383 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { |
384 return EncoderRowBased::CreateVerbatimEncoder(); | 384 return EncoderRowBased::CreateVerbatimEncoder(); |
385 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) { | 385 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) { |
386 return EncoderRowBased::CreateZlibEncoder(); | 386 return EncoderRowBased::CreateZlibEncoder(); |
387 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) { | 387 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) { |
388 return new remoting::EncoderVp8(); | 388 return new remoting::EncoderVp8(); |
389 } | 389 } |
390 | 390 |
391 return NULL; | 391 return NULL; |
392 } | 392 } |
393 | 393 |
394 void ChromotingHost::StopScreenRecorder() { | 394 void ChromotingHost::StopScreenRecorder() { |
395 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 395 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
396 DCHECK(recorder_.get()); | 396 DCHECK(recorder_.get()); |
397 | 397 |
398 ++stopping_recorders_; | 398 ++stopping_recorders_; |
399 scoped_refptr<ScreenRecorder> recorder = recorder_; | 399 scoped_refptr<ScreenRecorder> recorder = recorder_; |
400 recorder_ = NULL; | 400 recorder_ = NULL; |
401 recorder->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); | 401 recorder->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); |
402 } | 402 } |
403 | 403 |
404 void ChromotingHost::OnScreenRecorderStopped() { | 404 void ChromotingHost::OnScreenRecorderStopped() { |
405 if (!context_->network_message_loop()->BelongsToCurrentThread()) { | 405 if (!context_->network_task_runner()->BelongsToCurrentThread()) { |
406 context_->network_message_loop()->PostTask( | 406 context_->network_task_runner()->PostTask( |
407 FROM_HERE, base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); | 407 FROM_HERE, base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); |
408 return; | 408 return; |
409 } | 409 } |
410 | 410 |
411 --stopping_recorders_; | 411 --stopping_recorders_; |
412 DCHECK_GE(stopping_recorders_, 0); | 412 DCHECK_GE(stopping_recorders_, 0); |
413 | 413 |
414 if (!stopping_recorders_ && state_ == kStopping) | 414 if (!stopping_recorders_ && state_ == kStopping) |
415 ShutdownFinish(); | 415 ShutdownFinish(); |
416 } | 416 } |
417 | 417 |
418 void ChromotingHost::ShutdownFinish() { | 418 void ChromotingHost::ShutdownFinish() { |
419 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 419 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); |
420 DCHECK(!stopping_recorders_); | 420 DCHECK(!stopping_recorders_); |
421 | 421 |
422 state_ = kStopped; | 422 state_ = kStopped; |
423 | 423 |
424 // Keep reference to |this|, so that we don't get destroyed while | 424 // Keep reference to |this|, so that we don't get destroyed while |
425 // sending notifications. | 425 // sending notifications. |
426 scoped_refptr<ChromotingHost> self(this); | 426 scoped_refptr<ChromotingHost> self(this); |
427 | 427 |
428 // Notify observers. | 428 // Notify observers. |
429 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 429 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
430 OnShutdown()); | 430 OnShutdown()); |
431 | 431 |
432 for (std::vector<base::Closure>::iterator it = shutdown_tasks_.begin(); | 432 for (std::vector<base::Closure>::iterator it = shutdown_tasks_.begin(); |
433 it != shutdown_tasks_.end(); ++it) { | 433 it != shutdown_tasks_.end(); ++it) { |
434 it->Run(); | 434 it->Run(); |
435 } | 435 } |
436 shutdown_tasks_.clear(); | 436 shutdown_tasks_.clear(); |
437 } | 437 } |
438 | 438 |
439 } // namespace remoting | 439 } // namespace remoting |
OLD | NEW |