Index: remoting/client/chromoting_client.cc |
diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc |
index a9cf5ba551707457b93ab243e52a33297a7be0ad..e4f93ab6b533c7e571a8c9e4aeae8907eb969b82 100644 |
--- a/remoting/client/chromoting_client.cc |
+++ b/remoting/client/chromoting_client.cc |
@@ -5,10 +5,12 @@ |
#include "remoting/client/chromoting_client.h" |
#include "base/message_loop.h" |
+#include "remoting/base/tracer.h" |
#include "remoting/client/chromoting_view.h" |
#include "remoting/client/client_context.h" |
#include "remoting/client/host_connection.h" |
#include "remoting/client/input_handler.h" |
+#include "remoting/client/rectangle_update_decoder.h" |
static const uint32 kCreatedColor = 0xffccccff; |
static const uint32 kDisconnectedColor = 0xff00ccff; |
@@ -20,15 +22,18 @@ ChromotingClient::ChromotingClient(const ClientConfig& config, |
ClientContext* context, |
HostConnection* connection, |
ChromotingView* view, |
+ RectangleUpdateDecoder* rectangle_decoder, |
InputHandler* input_handler, |
CancelableTask* client_done) |
: config_(config), |
context_(context), |
connection_(connection), |
view_(view), |
+ rectangle_decoder_(rectangle_decoder), |
input_handler_(input_handler), |
client_done_(client_done), |
- state_(CREATED) { |
+ state_(CREATED), |
+ message_being_processed_(false) { |
} |
ChromotingClient::~ChromotingClient() { |
@@ -101,24 +106,51 @@ void ChromotingClient::HandleMessages(HostConnection* conn, |
return; |
} |
- for (size_t i = 0; i < messages->size(); ++i) { |
- ChromotingHostMessage* msg = (*messages)[i]; |
- // TODO(ajwong): Consider creating a macro similar to the IPC message |
- // mappings. Also reconsider the lifetime of the message object. |
- if (msg->has_init_client()) { |
- InitClient(msg); |
- } else if (msg->has_begin_update_stream()) { |
- BeginUpdate(msg); |
- } else if (msg->has_update_stream_packet()) { |
- HandleUpdate(msg); |
- } else if (msg->has_end_update_stream()) { |
- EndUpdate(msg); |
- } else { |
- NOTREACHED() << "Unknown message received"; |
- } |
+ // Put all messages in the queue. |
+ received_messages_.splice(received_messages_.end(), *messages); |
+ |
+ if (!message_being_processed_) { |
+ DispatchMessage(); |
+ } |
+} |
+ |
+void ChromotingClient::DispatchMessage() { |
+ DCHECK_EQ(message_loop(), MessageLoop::current()); |
+ CHECK(!message_being_processed_); |
+ |
+ if (received_messages_.empty()) { |
+ // Nothing to do! |
+ return; |
+ } |
+ |
+ ChromotingHostMessage* msg = received_messages_.front(); |
+ received_messages_.pop_front(); |
+ message_being_processed_ = true; |
+ |
+ // TODO(ajwong): Consider creating a macro similar to the IPC message |
+ // mappings. Also reconsider the lifetime of the message object. |
+ if (msg->has_init_client()) { |
+ ScopedTracer tracer("Handle Init Client"); |
+ // TODO(ajwong): Change this to use a done callback. |
+ InitClient(msg->init_client(), |
+ NewTracedMethod(this, &ChromotingClient::OnMessageDone, msg)); |
+ } else if (msg->has_rectangle_update()) { |
+ ScopedTracer tracer("Handle Rectangle Update"); |
+ rectangle_decoder_->DecodePacket( |
+ msg->rectangle_update(), |
+ NewTracedMethod(this, &ChromotingClient::OnMessageDone, msg)); |
+ } else { |
+ NOTREACHED() << "Unknown message received"; |
+ |
+ // We have an unknown message. Drop it, and schedule another dispatch. |
+ // Call DispatchMessage as a continuation to avoid growing the stack. |
+ delete msg; |
+ message_being_processed_ = false; |
+ message_loop()->PostTask( |
+ FROM_HERE, |
+ NewTracedMethod(this, &ChromotingClient::DispatchMessage)); |
+ return; |
} |
- // Assume we have processed all the messages. |
- messages->clear(); |
} |
void ChromotingClient::OnConnectionOpened(HostConnection* conn) { |
@@ -172,41 +204,40 @@ void ChromotingClient::SetState(State s) { |
Repaint(); |
} |
-void ChromotingClient::InitClient(ChromotingHostMessage* msg) { |
- DCHECK_EQ(message_loop(), MessageLoop::current()); |
- DCHECK(msg->has_init_client()); |
- scoped_ptr<ChromotingHostMessage> deleter(msg); |
- |
- // Resize the window. |
- int width = msg->init_client().width(); |
- int height = msg->init_client().height(); |
- LOG(INFO) << "Init client received geometry: " << width << "x" << height; |
+void ChromotingClient::OnMessageDone(ChromotingHostMessage* msg) { |
+ if (message_loop() != MessageLoop::current()) { |
+ message_loop()->PostTask( |
+ FROM_HERE, |
+ NewTracedMethod(this, &ChromotingClient::OnMessageDone, msg)); |
+ return; |
+ } |
- view_->SetHostScreenSize(width, height); |
+ TraceContext::tracer()->PrintString("Message done"); |
- // Schedule the input handler to process the event queue. |
- input_handler_->Initialize(); |
+ message_being_processed_ = false; |
+ delete msg; |
+ DispatchMessage(); |
} |
-void ChromotingClient::BeginUpdate(ChromotingHostMessage* msg) { |
+void ChromotingClient::InitClient(const InitClientMessage& init_client, |
+ Task* done) { |
DCHECK_EQ(message_loop(), MessageLoop::current()); |
- DCHECK(msg->has_begin_update_stream()); |
- |
- view_->HandleBeginUpdateStream(msg); |
-} |
+ TraceContext::tracer()->PrintString("Init received"); |
-void ChromotingClient::HandleUpdate(ChromotingHostMessage* msg) { |
- DCHECK_EQ(message_loop(), MessageLoop::current()); |
- DCHECK(msg->has_update_stream_packet()); |
+ // Resize the window. |
+ int width = init_client.width(); |
+ int height = init_client.height(); |
+ LOG(INFO) << "Init client received geometry: " << width << "x" << height; |
- view_->HandleUpdateStreamPacket(msg); |
-} |
+// TODO(ajwong): What to do here? Does the decoder actually need to request |
+// the right frame size? This is mainly an optimization right? |
+// rectangle_decoder_->SetOutputFrameSize(width, height); |
-void ChromotingClient::EndUpdate(ChromotingHostMessage* msg) { |
- DCHECK_EQ(message_loop(), MessageLoop::current()); |
- DCHECK(msg->has_end_update_stream()); |
+ // Schedule the input handler to process the event queue. |
+ input_handler_->Initialize(); |
- view_->HandleEndUpdateStream(msg); |
+ done->Run(); |
+ delete done; |
} |
} // namespace remoting |