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 |