| 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/client/chromoting_client.h" | 5 #include "remoting/client/chromoting_client.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop.h" | |
| 9 #include "jingle/glue/thread_wrapper.h" | 8 #include "jingle/glue/thread_wrapper.h" |
| 10 #include "remoting/base/tracer.h" | 9 #include "remoting/base/tracer.h" |
| 11 #include "remoting/client/chromoting_view.h" | 10 #include "remoting/client/chromoting_view.h" |
| 12 #include "remoting/client/client_context.h" | 11 #include "remoting/client/client_context.h" |
| 13 #include "remoting/client/input_handler.h" | 12 #include "remoting/client/input_handler.h" |
| 14 #include "remoting/client/rectangle_update_decoder.h" | 13 #include "remoting/client/rectangle_update_decoder.h" |
| 15 #include "remoting/protocol/connection_to_host.h" | 14 #include "remoting/protocol/connection_to_host.h" |
| 16 #include "remoting/protocol/session_config.h" | 15 #include "remoting/protocol/session_config.h" |
| 17 | 16 |
| 18 namespace remoting { | 17 namespace remoting { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 33 client_done_(client_done), | 32 client_done_(client_done), |
| 34 state_(CREATED), | 33 state_(CREATED), |
| 35 packet_being_processed_(false), | 34 packet_being_processed_(false), |
| 36 last_sequence_number_(0) { | 35 last_sequence_number_(0) { |
| 37 } | 36 } |
| 38 | 37 |
| 39 ChromotingClient::~ChromotingClient() { | 38 ChromotingClient::~ChromotingClient() { |
| 40 } | 39 } |
| 41 | 40 |
| 42 void ChromotingClient::Start(scoped_refptr<XmppProxy> xmpp_proxy) { | 41 void ChromotingClient::Start(scoped_refptr<XmppProxy> xmpp_proxy) { |
| 43 if (message_loop() != MessageLoop::current()) { | 42 if (!message_loop()->BelongsToCurrentThread()) { |
| 44 message_loop()->PostTask( | 43 message_loop()->PostTask( |
| 45 FROM_HERE, | 44 FROM_HERE, |
| 46 NewRunnableMethod(this, &ChromotingClient::Start, xmpp_proxy)); | 45 NewRunnableMethod(this, &ChromotingClient::Start, xmpp_proxy)); |
| 47 return; | 46 return; |
| 48 } | 47 } |
| 49 | 48 |
| 50 jingle_glue::JingleThreadWrapper::EnsureForCurrentThread(); | 49 jingle_glue::JingleThreadWrapper::EnsureForCurrentThread(); |
| 51 | 50 |
| 52 connection_->Connect(xmpp_proxy, config_.local_jid, config_.host_jid, | 51 connection_->Connect(xmpp_proxy, config_.local_jid, config_.host_jid, |
| 53 config_.host_public_key, config_.access_code, | 52 config_.host_public_key, config_.access_code, |
| 54 this, this, this); | 53 this, this, this); |
| 55 | 54 |
| 56 if (!view_->Initialize()) { | 55 if (!view_->Initialize()) { |
| 57 ClientDone(); | 56 ClientDone(); |
| 58 } | 57 } |
| 59 } | 58 } |
| 60 | 59 |
| 61 void ChromotingClient::Stop(const base::Closure& shutdown_task) { | 60 void ChromotingClient::Stop(const base::Closure& shutdown_task) { |
| 62 if (message_loop() != MessageLoop::current()) { | 61 if (!message_loop()->BelongsToCurrentThread()) { |
| 63 message_loop()->PostTask( | 62 message_loop()->PostTask( |
| 64 FROM_HERE, base::Bind(&ChromotingClient::Stop, | 63 FROM_HERE, base::Bind(&ChromotingClient::Stop, |
| 65 base::Unretained(this), shutdown_task)); | 64 base::Unretained(this), shutdown_task)); |
| 66 return; | 65 return; |
| 67 } | 66 } |
| 68 | 67 |
| 69 connection_->Disconnect(base::Bind(&ChromotingClient::OnDisconnected, | 68 connection_->Disconnect(base::Bind(&ChromotingClient::OnDisconnected, |
| 70 base::Unretained(this), shutdown_task)); | 69 base::Unretained(this), shutdown_task)); |
| 71 } | 70 } |
| 72 | 71 |
| 73 void ChromotingClient::OnDisconnected(const base::Closure& shutdown_task) { | 72 void ChromotingClient::OnDisconnected(const base::Closure& shutdown_task) { |
| 74 view_->TearDown(); | 73 view_->TearDown(); |
| 75 | 74 |
| 76 shutdown_task.Run(); | 75 shutdown_task.Run(); |
| 77 } | 76 } |
| 78 | 77 |
| 79 void ChromotingClient::ClientDone() { | 78 void ChromotingClient::ClientDone() { |
| 80 if (client_done_ != NULL) { | 79 if (client_done_ != NULL) { |
| 81 message_loop()->PostTask(FROM_HERE, client_done_); | 80 message_loop()->PostTask(FROM_HERE, client_done_); |
| 82 } | 81 } |
| 83 } | 82 } |
| 84 | 83 |
| 85 ChromotingStats* ChromotingClient::GetStats() { | 84 ChromotingStats* ChromotingClient::GetStats() { |
| 86 return &stats_; | 85 return &stats_; |
| 87 } | 86 } |
| 88 | 87 |
| 89 void ChromotingClient::Repaint() { | 88 void ChromotingClient::Repaint() { |
| 90 if (message_loop() != MessageLoop::current()) { | 89 if (!message_loop()->BelongsToCurrentThread()) { |
| 91 message_loop()->PostTask( | 90 message_loop()->PostTask( |
| 92 FROM_HERE, | 91 FROM_HERE, |
| 93 NewRunnableMethod(this, &ChromotingClient::Repaint)); | 92 NewRunnableMethod(this, &ChromotingClient::Repaint)); |
| 94 return; | 93 return; |
| 95 } | 94 } |
| 96 | 95 |
| 97 view_->Paint(); | 96 view_->Paint(); |
| 98 } | 97 } |
| 99 | 98 |
| 100 void ChromotingClient::ProcessVideoPacket(const VideoPacket* packet, | 99 void ChromotingClient::ProcessVideoPacket(const VideoPacket* packet, |
| 101 Task* done) { | 100 Task* done) { |
| 102 if (message_loop() != MessageLoop::current()) { | 101 if (!message_loop()->BelongsToCurrentThread()) { |
| 103 message_loop()->PostTask( | 102 message_loop()->PostTask( |
| 104 FROM_HERE, | 103 FROM_HERE, |
| 105 NewRunnableMethod(this, &ChromotingClient::ProcessVideoPacket, | 104 NewRunnableMethod(this, &ChromotingClient::ProcessVideoPacket, |
| 106 packet, done)); | 105 packet, done)); |
| 107 return; | 106 return; |
| 108 } | 107 } |
| 109 | 108 |
| 110 // If the video packet is empty then drop it. Empty packets are used to | 109 // If the video packet is empty then drop it. Empty packets are used to |
| 111 // maintain activity on the network. | 110 // maintain activity on the network. |
| 112 if (!packet->has_data() || packet->data().size() == 0) { | 111 if (!packet->has_data() || packet->data().size() == 0) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 135 received_packets_.push_back(QueuedVideoPacket(packet, done)); | 134 received_packets_.push_back(QueuedVideoPacket(packet, done)); |
| 136 if (!packet_being_processed_) | 135 if (!packet_being_processed_) |
| 137 DispatchPacket(); | 136 DispatchPacket(); |
| 138 } | 137 } |
| 139 | 138 |
| 140 int ChromotingClient::GetPendingPackets() { | 139 int ChromotingClient::GetPendingPackets() { |
| 141 return received_packets_.size(); | 140 return received_packets_.size(); |
| 142 } | 141 } |
| 143 | 142 |
| 144 void ChromotingClient::DispatchPacket() { | 143 void ChromotingClient::DispatchPacket() { |
| 145 DCHECK_EQ(message_loop(), MessageLoop::current()); | 144 DCHECK(message_loop()->BelongsToCurrentThread()); |
| 146 CHECK(!packet_being_processed_); | 145 CHECK(!packet_being_processed_); |
| 147 | 146 |
| 148 if (received_packets_.empty()) { | 147 if (received_packets_.empty()) { |
| 149 // Nothing to do! | 148 // Nothing to do! |
| 150 return; | 149 return; |
| 151 } | 150 } |
| 152 | 151 |
| 153 const VideoPacket* packet = received_packets_.front().packet; | 152 const VideoPacket* packet = received_packets_.front().packet; |
| 154 packet_being_processed_ = true; | 153 packet_being_processed_ = true; |
| 155 | 154 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 175 void ChromotingClient::OnConnectionClosed(protocol::ConnectionToHost* conn) { | 174 void ChromotingClient::OnConnectionClosed(protocol::ConnectionToHost* conn) { |
| 176 VLOG(1) << "ChromotingClient::OnConnectionClosed"; | 175 VLOG(1) << "ChromotingClient::OnConnectionClosed"; |
| 177 SetConnectionState(DISCONNECTED); | 176 SetConnectionState(DISCONNECTED); |
| 178 } | 177 } |
| 179 | 178 |
| 180 void ChromotingClient::OnConnectionFailed(protocol::ConnectionToHost* conn) { | 179 void ChromotingClient::OnConnectionFailed(protocol::ConnectionToHost* conn) { |
| 181 VLOG(1) << "ChromotingClient::OnConnectionFailed"; | 180 VLOG(1) << "ChromotingClient::OnConnectionFailed"; |
| 182 SetConnectionState(FAILED); | 181 SetConnectionState(FAILED); |
| 183 } | 182 } |
| 184 | 183 |
| 185 MessageLoop* ChromotingClient::message_loop() { | 184 base::MessageLoopProxy* ChromotingClient::message_loop() { |
| 186 return context_->network_message_loop(); | 185 return context_->network_message_loop(); |
| 187 } | 186 } |
| 188 | 187 |
| 189 void ChromotingClient::SetConnectionState(ConnectionState s) { | 188 void ChromotingClient::SetConnectionState(ConnectionState s) { |
| 190 // TODO(ajwong): We actually may want state to be a shared variable. Think | 189 // TODO(ajwong): We actually may want state to be a shared variable. Think |
| 191 // through later. | 190 // through later. |
| 192 if (message_loop() != MessageLoop::current()) { | 191 if (!message_loop()->BelongsToCurrentThread()) { |
| 193 message_loop()->PostTask( | 192 message_loop()->PostTask( |
| 194 FROM_HERE, | 193 FROM_HERE, |
| 195 NewRunnableMethod(this, &ChromotingClient::SetConnectionState, s)); | 194 NewRunnableMethod(this, &ChromotingClient::SetConnectionState, s)); |
| 196 return; | 195 return; |
| 197 } | 196 } |
| 198 | 197 |
| 199 state_ = s; | 198 state_ = s; |
| 200 view_->SetConnectionState(s); | 199 view_->SetConnectionState(s); |
| 201 | 200 |
| 202 Repaint(); | 201 Repaint(); |
| 203 } | 202 } |
| 204 | 203 |
| 205 void ChromotingClient::OnPacketDone(bool last_packet, | 204 void ChromotingClient::OnPacketDone(bool last_packet, |
| 206 base::Time decode_start) { | 205 base::Time decode_start) { |
| 207 if (message_loop() != MessageLoop::current()) { | 206 if (!message_loop()->BelongsToCurrentThread()) { |
| 208 message_loop()->PostTask( | 207 message_loop()->PostTask( |
| 209 FROM_HERE, | 208 FROM_HERE, |
| 210 NewTracedMethod(this, &ChromotingClient::OnPacketDone, | 209 NewTracedMethod(this, &ChromotingClient::OnPacketDone, |
| 211 last_packet, decode_start)); | 210 last_packet, decode_start)); |
| 212 return; | 211 return; |
| 213 } | 212 } |
| 214 | 213 |
| 215 TraceContext::tracer()->PrintString("Packet done"); | 214 TraceContext::tracer()->PrintString("Packet done"); |
| 216 | 215 |
| 217 // Record the latency between the final packet being received and | 216 // Record the latency between the final packet being received and |
| 218 // presented. | 217 // presented. |
| 219 if (last_packet) { | 218 if (last_packet) { |
| 220 stats_.video_decode_ms()->Record( | 219 stats_.video_decode_ms()->Record( |
| 221 (base::Time::Now() - decode_start).InMilliseconds()); | 220 (base::Time::Now() - decode_start).InMilliseconds()); |
| 222 } | 221 } |
| 223 | 222 |
| 224 received_packets_.front().done->Run(); | 223 received_packets_.front().done->Run(); |
| 225 delete received_packets_.front().done; | 224 delete received_packets_.front().done; |
| 226 received_packets_.pop_front(); | 225 received_packets_.pop_front(); |
| 227 | 226 |
| 228 packet_being_processed_ = false; | 227 packet_being_processed_ = false; |
| 229 | 228 |
| 230 // Process the next video packet. | 229 // Process the next video packet. |
| 231 DispatchPacket(); | 230 DispatchPacket(); |
| 232 } | 231 } |
| 233 | 232 |
| 234 void ChromotingClient::Initialize() { | 233 void ChromotingClient::Initialize() { |
| 235 if (message_loop() != MessageLoop::current()) { | 234 if (!message_loop()->BelongsToCurrentThread()) { |
| 236 message_loop()->PostTask( | 235 message_loop()->PostTask( |
| 237 FROM_HERE, | 236 FROM_HERE, |
| 238 NewTracedMethod(this, &ChromotingClient::Initialize)); | 237 NewTracedMethod(this, &ChromotingClient::Initialize)); |
| 239 return; | 238 return; |
| 240 } | 239 } |
| 241 | 240 |
| 242 TraceContext::tracer()->PrintString("Initializing client."); | 241 TraceContext::tracer()->PrintString("Initializing client."); |
| 243 | 242 |
| 244 const protocol::SessionConfig* config = connection_->config(); | 243 const protocol::SessionConfig* config = connection_->config(); |
| 245 | 244 |
| 246 // Initialize the decoder. | 245 // Initialize the decoder. |
| 247 rectangle_decoder_->Initialize(config); | 246 rectangle_decoder_->Initialize(config); |
| 248 | 247 |
| 249 // Schedule the input handler to process the event queue. | 248 // Schedule the input handler to process the event queue. |
| 250 input_handler_->Initialize(); | 249 input_handler_->Initialize(); |
| 251 } | 250 } |
| 252 | 251 |
| 253 //////////////////////////////////////////////////////////////////////////// | 252 //////////////////////////////////////////////////////////////////////////// |
| 254 // ClientStub control channel interface. | 253 // ClientStub control channel interface. |
| 255 void ChromotingClient::BeginSessionResponse( | 254 void ChromotingClient::BeginSessionResponse( |
| 256 const protocol::LocalLoginStatus* msg, Task* done) { | 255 const protocol::LocalLoginStatus* msg, Task* done) { |
| 257 if (message_loop() != MessageLoop::current()) { | 256 if (!message_loop()->BelongsToCurrentThread()) { |
| 258 message_loop()->PostTask( | 257 message_loop()->PostTask( |
| 259 FROM_HERE, | 258 FROM_HERE, |
| 260 NewRunnableMethod(this, &ChromotingClient::BeginSessionResponse, | 259 NewRunnableMethod(this, &ChromotingClient::BeginSessionResponse, |
| 261 msg, done)); | 260 msg, done)); |
| 262 return; | 261 return; |
| 263 } | 262 } |
| 264 | 263 |
| 265 LOG(INFO) << "BeginSessionResponse received"; | 264 LOG(INFO) << "BeginSessionResponse received"; |
| 266 | 265 |
| 267 // Inform the connection that the client has been authenticated. This will | 266 // Inform the connection that the client has been authenticated. This will |
| 268 // enable the communication channels. | 267 // enable the communication channels. |
| 269 if (msg->success()) { | 268 if (msg->success()) { |
| 270 connection_->OnClientAuthenticated(); | 269 connection_->OnClientAuthenticated(); |
| 271 } | 270 } |
| 272 | 271 |
| 273 view_->UpdateLoginStatus(msg->success(), msg->error_info()); | 272 view_->UpdateLoginStatus(msg->success(), msg->error_info()); |
| 274 done->Run(); | 273 done->Run(); |
| 275 delete done; | 274 delete done; |
| 276 } | 275 } |
| 277 | 276 |
| 278 } // namespace remoting | 277 } // namespace remoting |
| OLD | NEW |