summaryrefslogtreecommitdiffstats
path: root/blimp
diff options
context:
space:
mode:
authordtrainor <dtrainor@chromium.org>2015-11-29 21:03:40 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-30 05:04:35 +0000
commit6086a92c956e7bd81aa402b2e4dc4ec6a91c8585 (patch)
treef3c55e73cc178ecd873d1c3843703d8fcc8f75c9 /blimp
parent27aa4f7ee504d5b2d86f025620bca43d43fa285d (diff)
downloadchromium_src-6086a92c956e7bd81aa402b2e4dc4ec6a91c8585.zip
chromium_src-6086a92c956e7bd81aa402b2e4dc4ec6a91c8585.tar.gz
chromium_src-6086a92c956e7bd81aa402b2e4dc4ec6a91c8585.tar.bz2
Serialize a subset of WebInputEvents to protobufs.
- Add (de)serialization methods for WebGestureEvents (a subset of WebInputEvents). - Add unit tests to validate that moving to and from these events works properly. BUG=548806 Review URL: https://codereview.chromium.org/1426993008 Cr-Commit-Position: refs/heads/master@{#362089}
Diffstat (limited to 'blimp')
-rw-r--r--blimp/common/proto/input.proto82
-rw-r--r--blimp/net/BUILD.gn5
-rw-r--r--blimp/net/DEPS2
-rw-r--r--blimp/net/blimp_message_multiplexer_unittest.cc15
-rw-r--r--blimp/net/input_message_generator.cc195
-rw-r--r--blimp/net/input_message_generator.h43
-rw-r--r--blimp/net/input_message_processor.cc181
-rw-r--r--blimp/net/input_message_processor.h38
-rw-r--r--blimp/net/input_message_unittest.cc133
9 files changed, 677 insertions, 17 deletions
diff --git a/blimp/common/proto/input.proto b/blimp/common/proto/input.proto
index bc05dd3..fa6fe62 100644
--- a/blimp/common/proto/input.proto
+++ b/blimp/common/proto/input.proto
@@ -4,8 +4,8 @@
//
// Message definitions for the input subprotocol.
//
-// Current definitions are just placeholders and are NOT final.
-// Feel free to modify this interface as necessary during feature work.
+// The InputMessage protobuf generally carries web input events. Currently we
+// just serialize the blink::WebInputEvent POD struct.
syntax = "proto2";
@@ -15,25 +15,83 @@ import "common.proto";
package blimp;
-message ClickArgs {
- optional CoordinatePair target = 1;
+message GestureCommon {
+ optional int64 x = 1;
+ optional int64 y = 2;
+ optional int64 global_x = 3;
+ optional int64 global_y = 4;
}
-message DragArgs {
- optional CoordinatePair origin = 1;
- optional CoordinatePair destination = 2;
- optional CoordinatePair elastic_overscroll = 3;
+message GestureScrollBegin {
+ optional float delta_x_hint = 1;
+ optional float delta_y_hint = 2;
+ optional bool target_viewport = 3;
+}
+
+message GestureScrollUpdate {
+ optional float delta_x = 1;
+ optional float delta_y = 2;
+ optional float velocity_x = 3;
+ optional float velocity_y = 4;
+ optional bool previous_update_in_sequence_prevented = 5;
+ optional bool prevent_propagation = 6;
+ optional bool inertial = 7;
+}
+
+message GestureFlingStart {
+ optional float velocity_x = 1;
+ optional float velocity_y = 2;
+ optional bool target_viewport = 3;
+}
+
+message GestureFlingCancel {
+ optional bool prevent_boosting = 1;
+}
+
+message GestureTap {
+ optional int32 tap_count = 1;
+ optional float width = 2;
+ optional float height = 3;
+}
+
+message GesturePinchUpdate {
+ optional bool zoom_disabled = 1;
+ optional float scale = 2;
}
message InputMessage {
enum Type {
UNKNOWN = 0;
- CLICK = 1;
- DRAG = 2;
+
+ // This is a subset of WebGestureType events. We only support a small set
+ // of these with the existing protocol.
+ Type_GestureScrollBegin = 1;
+ Type_GestureScrollEnd = 2;
+ Type_GestureScrollUpdate = 3;
+ Type_GestureFlingStart = 4;
+ Type_GestureFlingCancel = 5;
+ Type_GestureTap = 6;
+ Type_GesturePinchBegin = 7;
+ Type_GesturePinchEnd = 8;
+ Type_GesturePinchUpdate = 9;
}
+
optional Type type = 1;
- optional ClickArgs click = 1000;
- optional DragArgs drag = 1001;
+ // Seconds since client platform start (boot) with millisecond resolution.
+ // On Android, this is based off of the client's SystemClock#uptimeMillis().
+ optional double timestamp_seconds = 2;
+
+ optional GestureCommon gesture_common = 3;
+
+ // Input event specific messages follow.
+ // Only one of these fields may be set per InputMessage.
+ // TODO(dtrainor): use a 'oneof' union when it's supported in Chromium.
+ optional GestureScrollBegin gesture_scroll_begin = 4;
+ optional GestureScrollUpdate gesture_scroll_update = 5;
+ optional GestureFlingStart gesture_fling_start = 6;
+ optional GestureFlingCancel gesture_fling_cancel = 7;
+ optional GestureTap gesture_tap = 8;
+ optional GesturePinchUpdate gesture_pinch_update = 9;
}
diff --git a/blimp/net/BUILD.gn b/blimp/net/BUILD.gn
index e745099..63de25b 100644
--- a/blimp/net/BUILD.gn
+++ b/blimp/net/BUILD.gn
@@ -27,6 +27,10 @@ component("blimp_net") {
"connection_handler.h",
"engine_connection_manager.cc",
"engine_connection_manager.h",
+ "input_message_generator.cc",
+ "input_message_generator.h",
+ "input_message_processor.cc",
+ "input_message_processor.h",
"stream_packet_reader.cc",
"stream_packet_reader.h",
"stream_packet_writer.cc",
@@ -56,6 +60,7 @@ source_set("unit_tests") {
"blimp_message_demultiplexer_unittest.cc",
"blimp_message_multiplexer_unittest.cc",
"blimp_message_pump_unittest.cc",
+ "input_message_unittest.cc",
"stream_packet_reader_unittest.cc",
"stream_packet_writer_unittest.cc",
"tcp_transport_unittest.cc",
diff --git a/blimp/net/DEPS b/blimp/net/DEPS
index 7bb1081..9891086 100644
--- a/blimp/net/DEPS
+++ b/blimp/net/DEPS
@@ -1,4 +1,6 @@
include_rules = [
"+net/base",
"+net/socket",
+ "+third_party/WebKit/public/platform/WebGestureDevice.h",
+ "+third_party/WebKit/public/web/WebInputEvent.h",
]
diff --git a/blimp/net/blimp_message_multiplexer_unittest.cc b/blimp/net/blimp_message_multiplexer_unittest.cc
index 4c757b2..7a4028f 100644
--- a/blimp/net/blimp_message_multiplexer_unittest.cc
+++ b/blimp/net/blimp_message_multiplexer_unittest.cc
@@ -35,7 +35,8 @@ class BlimpMessageMultiplexerTest : public testing::Test {
.WillRepeatedly(
DoAll(SaveArg<0>(&captured_message_), SaveArg<1>(&captured_cb_)));
- input_message_->mutable_input()->set_type(InputMessage::DRAG);
+ input_message_->mutable_input()->set_type(
+ InputMessage::Type_GestureScrollBegin);
navigation_message_->mutable_navigation()->set_type(
NavigationMessage::LOAD_URL);
}
@@ -57,7 +58,8 @@ TEST_F(BlimpMessageMultiplexerTest, TypeSetByMux) {
net::TestCompletionCallback cb_1;
input_processor_->ProcessMessage(input_message_.Pass(), cb_1.callback());
EXPECT_EQ(BlimpMessage::INPUT, captured_message_.type());
- EXPECT_EQ(InputMessage::DRAG, captured_message_.input().type());
+ EXPECT_EQ(InputMessage::Type_GestureScrollBegin,
+ captured_message_.input().type());
captured_cb_.Run(net::OK);
EXPECT_EQ(net::OK, cb_1.WaitForResult());
@@ -77,7 +79,8 @@ TEST_F(BlimpMessageMultiplexerTest, TypeSetByCaller) {
net::TestCompletionCallback cb_1;
input_processor_->ProcessMessage(input_message_.Pass(), cb_1.callback());
EXPECT_EQ(BlimpMessage::INPUT, captured_message_.type());
- EXPECT_EQ(InputMessage::DRAG, captured_message_.input().type());
+ EXPECT_EQ(InputMessage::Type_GestureScrollBegin,
+ captured_message_.input().type());
captured_cb_.Run(net::OK);
EXPECT_EQ(net::OK, cb_1.WaitForResult());
}
@@ -88,7 +91,8 @@ TEST_F(BlimpMessageMultiplexerTest, SenderTransience) {
input_processor_ = multiplexer_.CreateSenderForType(BlimpMessage::INPUT);
input_processor_->ProcessMessage(input_message_.Pass(), cb_3.callback());
EXPECT_EQ(BlimpMessage::INPUT, captured_message_.type());
- EXPECT_EQ(InputMessage::DRAG, captured_message_.input().type());
+ EXPECT_EQ(InputMessage::Type_GestureScrollBegin,
+ captured_message_.input().type());
captured_cb_.Run(net::OK);
EXPECT_EQ(net::OK, cb_3.WaitForResult());
}
@@ -100,7 +104,8 @@ TEST_F(BlimpMessageMultiplexerTest, SenderMultiplicity) {
multiplexer_.CreateSenderForType(BlimpMessage::INPUT);
input_processor_2->ProcessMessage(input_message_.Pass(), cb_4.callback());
EXPECT_EQ(BlimpMessage::INPUT, captured_message_.type());
- EXPECT_EQ(InputMessage::DRAG, captured_message_.input().type());
+ EXPECT_EQ(InputMessage::Type_GestureScrollBegin,
+ captured_message_.input().type());
captured_cb_.Run(net::ERR_INVALID_ARGUMENT);
EXPECT_EQ(net::ERR_INVALID_ARGUMENT, cb_4.WaitForResult());
}
diff --git a/blimp/net/input_message_generator.cc b/blimp/net/input_message_generator.cc
new file mode 100644
index 0000000..ae0eef0
--- /dev/null
+++ b/blimp/net/input_message_generator.cc
@@ -0,0 +1,195 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "blimp/net/input_message_generator.h"
+
+#include "base/logging.h"
+#include "blimp/common/proto/blimp_message.pb.h"
+#include "blimp/common/proto/input.pb.h"
+#include "blimp/net/blimp_message_processor.h"
+#include "third_party/WebKit/public/platform/WebGestureDevice.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace blimp {
+namespace {
+
+void CommonWebGestureToProto(const blink::WebGestureEvent& event,
+ InputMessage::Type type,
+ InputMessage* proto) {
+ proto->set_type(type);
+ proto->set_timestamp_seconds(event.timeStampSeconds);
+
+ GestureCommon* common = proto->mutable_gesture_common();
+ common->set_x(event.x);
+ common->set_y(event.y);
+ common->set_global_x(event.globalX);
+ common->set_global_y(event.globalY);
+}
+
+void GestureScrollBeginToProto(const blink::WebGestureEvent& event,
+ InputMessage* proto) {
+ CommonWebGestureToProto(event, InputMessage::Type_GestureScrollBegin, proto);
+
+ GestureScrollBegin* details = proto->mutable_gesture_scroll_begin();
+ details->set_delta_x_hint(event.data.scrollBegin.deltaXHint);
+ details->set_delta_y_hint(event.data.scrollBegin.deltaYHint);
+ details->set_target_viewport(event.data.scrollBegin.targetViewport);
+}
+
+void GestureScrollEndToProto(const blink::WebGestureEvent& event,
+ InputMessage* proto) {
+ CommonWebGestureToProto(event, InputMessage::Type_GestureScrollEnd, proto);
+}
+
+void GestureScrollUpdateToProto(const blink::WebGestureEvent& event,
+ InputMessage* proto) {
+ CommonWebGestureToProto(event, InputMessage::Type_GestureScrollUpdate, proto);
+
+ GestureScrollUpdate* details = proto->mutable_gesture_scroll_update();
+ details->set_delta_x(event.data.scrollUpdate.deltaX);
+ details->set_delta_y(event.data.scrollUpdate.deltaY);
+ details->set_velocity_x(event.data.scrollUpdate.velocityX);
+ details->set_velocity_y(event.data.scrollUpdate.velocityY);
+ details->set_previous_update_in_sequence_prevented(
+ event.data.scrollUpdate.previousUpdateInSequencePrevented);
+ details->set_prevent_propagation(
+ event.data.scrollUpdate.preventPropagation);
+ details->set_inertial(event.data.scrollUpdate.inertial);
+}
+
+void GestureFlingStartToProto(const blink::WebGestureEvent& event,
+ InputMessage* proto) {
+ CommonWebGestureToProto(event, InputMessage::Type_GestureFlingStart, proto);
+
+ GestureFlingStart* details = proto->mutable_gesture_fling_start();
+ details->set_velocity_x(event.data.flingStart.velocityX);
+ details->set_velocity_y(event.data.flingStart.velocityY);
+ details->set_target_viewport(event.data.flingStart.targetViewport);
+}
+
+void GestureFlingCancelToProto(const blink::WebGestureEvent& event,
+ InputMessage* proto) {
+ CommonWebGestureToProto(event, InputMessage::Type_GestureFlingCancel, proto);
+
+ GestureFlingCancel* details = proto->mutable_gesture_fling_cancel();
+ details->set_prevent_boosting(event.data.flingCancel.preventBoosting);
+}
+
+void GestureTapToProto(const blink::WebGestureEvent& event,
+ InputMessage* proto) {
+ CommonWebGestureToProto(event, InputMessage::Type_GestureTap, proto);
+
+ GestureTap* details = proto->mutable_gesture_tap();
+ details->set_tap_count(event.data.tap.tapCount);
+ details->set_width(event.data.tap.width);
+ details->set_height(event.data.tap.height);
+}
+
+void GesturePinchBeginToProto(const blink::WebGestureEvent& event,
+ InputMessage* proto) {
+ CommonWebGestureToProto(event, InputMessage::Type_GesturePinchBegin, proto);
+}
+
+void GesturePinchEndToProto(const blink::WebGestureEvent& event,
+ InputMessage* proto) {
+ CommonWebGestureToProto(event, InputMessage::Type_GesturePinchEnd, proto);
+}
+
+void GesturePinchUpdateToProto(const blink::WebGestureEvent& event,
+ InputMessage* proto) {
+ CommonWebGestureToProto(event, InputMessage::Type_GesturePinchUpdate, proto);
+
+ GesturePinchUpdate* details = proto->mutable_gesture_pinch_update();
+ details->set_zoom_disabled(event.data.pinchUpdate.zoomDisabled);
+ details->set_scale(event.data.pinchUpdate.scale);
+}
+
+} // namespace
+
+InputMessageGenerator::InputMessageGenerator() {}
+
+InputMessageGenerator::~InputMessageGenerator() {}
+
+scoped_ptr<BlimpMessage> InputMessageGenerator::GenerateMessage(
+ const blink::WebInputEvent& event) {
+ scoped_ptr<BlimpMessage> message(new BlimpMessage);
+ message->set_type(BlimpMessage::INPUT);
+ InputMessage* details = message->mutable_input();
+
+ switch (event.type) {
+ case blink::WebInputEvent::Type::GestureScrollBegin:
+ GestureScrollBeginToProto(
+ static_cast<const blink::WebGestureEvent&>(event),
+ details);
+ break;
+ case blink::WebInputEvent::Type::GestureScrollEnd:
+ GestureScrollEndToProto(static_cast<const blink::WebGestureEvent&>(event),
+ details);
+ break;
+ case blink::WebInputEvent::Type::GestureScrollUpdate:
+ GestureScrollUpdateToProto(
+ static_cast<const blink::WebGestureEvent&>(event),
+ details);
+ break;
+ case blink::WebInputEvent::Type::GestureFlingStart:
+ GestureFlingStartToProto(
+ static_cast<const blink::WebGestureEvent&>(event),
+ details);
+ break;
+ case blink::WebInputEvent::Type::GestureFlingCancel:
+ GestureFlingCancelToProto(
+ static_cast<const blink::WebGestureEvent&>(event),
+ details);
+ break;
+ case blink::WebInputEvent::Type::GestureTap:
+ GestureTapToProto(static_cast<const blink::WebGestureEvent&>(event),
+ details);
+ break;
+ case blink::WebInputEvent::Type::GesturePinchBegin:
+ GesturePinchBeginToProto(
+ static_cast<const blink::WebGestureEvent&>(event),
+ details);
+ break;
+ case blink::WebInputEvent::Type::GesturePinchEnd:
+ GesturePinchEndToProto(static_cast<const blink::WebGestureEvent&>(event),
+ details);
+ break;
+ case blink::WebInputEvent::Type::GesturePinchUpdate:
+ GesturePinchUpdateToProto(
+ static_cast<const blink::WebGestureEvent&>(event),
+ details);
+ break;
+ // Unsupported types:
+ case blink::WebInputEvent::Type::Undefined:
+ case blink::WebInputEvent::Type::MouseDown:
+ case blink::WebInputEvent::Type::MouseUp:
+ case blink::WebInputEvent::Type::MouseMove:
+ case blink::WebInputEvent::Type::MouseEnter:
+ case blink::WebInputEvent::Type::MouseLeave:
+ case blink::WebInputEvent::Type::ContextMenu:
+ case blink::WebInputEvent::Type::MouseWheel:
+ case blink::WebInputEvent::Type::RawKeyDown:
+ case blink::WebInputEvent::Type::KeyDown:
+ case blink::WebInputEvent::Type::KeyUp:
+ case blink::WebInputEvent::Type::Char:
+ case blink::WebInputEvent::Type::GestureShowPress:
+ case blink::WebInputEvent::Type::GestureTapUnconfirmed:
+ case blink::WebInputEvent::Type::GestureTapDown:
+ case blink::WebInputEvent::Type::GestureTapCancel:
+ case blink::WebInputEvent::Type::GestureDoubleTap:
+ case blink::WebInputEvent::Type::GestureTwoFingerTap:
+ case blink::WebInputEvent::Type::GestureLongPress:
+ case blink::WebInputEvent::Type::GestureLongTap:
+ case blink::WebInputEvent::Type::TouchStart:
+ case blink::WebInputEvent::Type::TouchMove:
+ case blink::WebInputEvent::Type::TouchEnd:
+ case blink::WebInputEvent::Type::TouchCancel:
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+
+ return message;
+}
+
+} // namespace blimp
diff --git a/blimp/net/input_message_generator.h b/blimp/net/input_message_generator.h
new file mode 100644
index 0000000..0059ce4b
--- /dev/null
+++ b/blimp/net/input_message_generator.h
@@ -0,0 +1,43 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BLIMP_NET_INPUT_MESSAGE_GENERATOR_H_
+#define BLIMP_NET_INPUT_MESSAGE_GENERATOR_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "blimp/net/blimp_net_export.h"
+#include "net/base/completion_callback.h"
+
+namespace blink {
+class WebInputEvent;
+}
+
+namespace blimp {
+
+class BlimpMessage;
+class BlimpMessageProcessor;
+
+// Handles creating serialized InputMessage protos from a stream of
+// WebInputEvents. This class may be stateful to optimize the size of the
+// serialized transmission data. See InputMessageProcessor for the deserialize
+// code.
+class BLIMP_NET_EXPORT InputMessageGenerator {
+ public:
+ InputMessageGenerator();
+ ~InputMessageGenerator();
+
+ // Builds a BlimpMessage from |event| that has the basic input event fields
+ // populated. This might make use of state sent from previous
+ // BlimpMessage::INPUT messages. It is up to the caller to populate the
+ // non-input fields and to send the BlimpMessage.
+ scoped_ptr<BlimpMessage> GenerateMessage(const blink::WebInputEvent& event);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputMessageGenerator);
+};
+
+} // namespace blimp
+
+#endif // BLIMP_NET_INPUT_MESSAGE_GENERATOR_H_
diff --git a/blimp/net/input_message_processor.cc b/blimp/net/input_message_processor.cc
new file mode 100644
index 0000000..626e155
--- /dev/null
+++ b/blimp/net/input_message_processor.cc
@@ -0,0 +1,181 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "blimp/net/input_message_processor.h"
+
+#include "base/logging.h"
+#include "blimp/common/proto/input.pb.h"
+#include "third_party/WebKit/public/platform/WebGestureDevice.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace blimp {
+namespace {
+
+scoped_ptr<blink::WebGestureEvent> BuildCommonWebGesture(
+ const InputMessage& proto,
+ blink::WebInputEvent::Type type) {
+ scoped_ptr<blink::WebGestureEvent> event(new blink::WebGestureEvent);
+ event->type = type;
+ event->timeStampSeconds = proto.timestamp_seconds();
+
+ const GestureCommon& common = proto.gesture_common();
+ event->x = common.x();
+ event->y = common.y();
+ event->globalX = common.global_x();
+ event->globalY = common.global_y();
+ event->sourceDevice = blink::WebGestureDevice::WebGestureDeviceTouchscreen;
+ return event;
+}
+
+scoped_ptr<blink::WebInputEvent> ProtoToGestureScrollBegin(
+ const InputMessage& proto) {
+ scoped_ptr<blink::WebGestureEvent> event(
+ BuildCommonWebGesture(proto,
+ blink::WebInputEvent::Type::GestureScrollBegin));
+
+ const GestureScrollBegin& details = proto.gesture_scroll_begin();
+ event->data.scrollBegin.deltaXHint = details.delta_x_hint();
+ event->data.scrollBegin.deltaYHint = details.delta_y_hint();
+ event->data.scrollBegin.targetViewport = details.target_viewport();
+
+ return std::move(event);
+}
+
+scoped_ptr<blink::WebInputEvent> ProtoToGestureScrollEnd(
+ const InputMessage& proto) {
+ return BuildCommonWebGesture(proto,
+ blink::WebInputEvent::Type::GestureScrollEnd);
+}
+
+scoped_ptr<blink::WebInputEvent> ProtoToGestureScrollUpdate(
+ const InputMessage& proto) {
+ scoped_ptr<blink::WebGestureEvent> event(
+ BuildCommonWebGesture(proto,
+ blink::WebInputEvent::Type::GestureScrollUpdate));
+
+ const GestureScrollUpdate& details = proto.gesture_scroll_update();
+ event->data.scrollUpdate.deltaX = details.delta_x();
+ event->data.scrollUpdate.deltaY = details.delta_y();
+ event->data.scrollUpdate.velocityX = details.velocity_x();
+ event->data.scrollUpdate.velocityY = details.velocity_y();
+ event->data.scrollUpdate.previousUpdateInSequencePrevented =
+ details.previous_update_in_sequence_prevented();
+ event->data.scrollUpdate.preventPropagation = details.prevent_propagation();
+ event->data.scrollUpdate.inertial = details.inertial();
+
+ return std::move(event);
+}
+
+scoped_ptr<blink::WebInputEvent> ProtoToGestureFlingStart(
+ const InputMessage& proto) {
+ scoped_ptr<blink::WebGestureEvent> event(
+ BuildCommonWebGesture(proto,
+ blink::WebInputEvent::Type::GestureFlingStart));
+
+ const GestureFlingStart& details = proto.gesture_fling_start();
+ event->data.flingStart.velocityX = details.velocity_x();
+ event->data.flingStart.velocityY = details.velocity_y();
+ event->data.flingStart.targetViewport = details.target_viewport();
+
+ return std::move(event);
+}
+
+scoped_ptr<blink::WebInputEvent> ProtoToGestureFlingCancel(
+ const InputMessage& proto) {
+ scoped_ptr<blink::WebGestureEvent> event(
+ BuildCommonWebGesture(proto,
+ blink::WebInputEvent::Type::GestureFlingCancel));
+
+ const GestureFlingCancel& details = proto.gesture_fling_cancel();
+ event->data.flingCancel.preventBoosting = details.prevent_boosting();
+
+ return std::move(event);
+}
+
+scoped_ptr<blink::WebInputEvent> ProtoToGestureTap(
+ const InputMessage& proto) {
+ scoped_ptr<blink::WebGestureEvent> event(
+ BuildCommonWebGesture(proto,
+ blink::WebInputEvent::Type::GestureTap));
+
+ const GestureTap& details = proto.gesture_tap();
+ event->data.tap.tapCount = details.tap_count();
+ event->data.tap.width = details.width();
+ event->data.tap.height = details.height();
+
+ return std::move(event);
+}
+
+scoped_ptr<blink::WebInputEvent> ProtoToGesturePinchBegin(
+ const InputMessage& proto) {
+ return BuildCommonWebGesture(proto,
+ blink::WebInputEvent::Type::GesturePinchBegin);
+}
+
+scoped_ptr<blink::WebInputEvent> ProtoToGesturePinchEnd(
+ const InputMessage& proto) {
+ return BuildCommonWebGesture(proto,
+ blink::WebInputEvent::Type::GesturePinchEnd);
+}
+
+scoped_ptr<blink::WebInputEvent> ProtoToGesturePinchUpdate(
+ const InputMessage& proto) {
+ scoped_ptr<blink::WebGestureEvent> event(
+ BuildCommonWebGesture(proto,
+ blink::WebInputEvent::Type::GesturePinchUpdate));
+
+ const GesturePinchUpdate& details = proto.gesture_pinch_update();
+ event->data.pinchUpdate.zoomDisabled = details.zoom_disabled();
+ event->data.pinchUpdate.scale = details.scale();
+
+ return std::move(event);
+}
+
+} // namespace
+
+InputMessageProcessor::InputMessageProcessor() {}
+
+InputMessageProcessor::~InputMessageProcessor() {}
+
+scoped_ptr<blink::WebInputEvent> InputMessageProcessor::ProcessMessage(
+ const InputMessage& message) {
+ scoped_ptr<blink::WebInputEvent> event;
+
+ switch (message.type()) {
+ case InputMessage::Type_GestureScrollBegin:
+ event = ProtoToGestureScrollBegin(message);
+ break;
+ case InputMessage::Type_GestureScrollEnd:
+ event = ProtoToGestureScrollEnd(message);
+ break;
+ case InputMessage::Type_GestureScrollUpdate:
+ event = ProtoToGestureScrollUpdate(message);
+ break;
+ case InputMessage::Type_GestureFlingStart:
+ event = ProtoToGestureFlingStart(message);
+ break;
+ case InputMessage::Type_GestureFlingCancel:
+ event = ProtoToGestureFlingCancel(message);
+ break;
+ case InputMessage::Type_GestureTap:
+ event = ProtoToGestureTap(message);
+ break;
+ case InputMessage::Type_GesturePinchBegin:
+ event = ProtoToGesturePinchBegin(message);
+ break;
+ case InputMessage::Type_GesturePinchEnd:
+ event = ProtoToGesturePinchEnd(message);
+ break;
+ case InputMessage::Type_GesturePinchUpdate:
+ event = ProtoToGesturePinchUpdate(message);
+ break;
+ case InputMessage::UNKNOWN:
+ DLOG(FATAL) << "Received an InputMessage with an unknown type.";
+ return nullptr;
+ }
+
+ return event;
+}
+
+} // namespace blimp
diff --git a/blimp/net/input_message_processor.h b/blimp/net/input_message_processor.h
new file mode 100644
index 0000000..5a7ab1c
--- /dev/null
+++ b/blimp/net/input_message_processor.h
@@ -0,0 +1,38 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BLIMP_NET_INPUT_MESSAGE_PROCESSOR_H_
+#define BLIMP_NET_INPUT_MESSAGE_PROCESSOR_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "blimp/net/blimp_net_export.h"
+
+namespace blink {
+class WebInputEvent;
+}
+
+namespace blimp {
+
+class InputMessage;
+
+// Handles creating WebInputEvents from a stream of InputMessage protos. This
+// class may be stateful to optimize the size of the serialized transmission
+// data. See InputMessageProcessor for the deserialize code.
+class BLIMP_NET_EXPORT InputMessageProcessor {
+ public:
+ InputMessageProcessor();
+ ~InputMessageProcessor();
+
+ // Process an InputMessage and create a WebInputEvent from it. This might
+ // make use of state from previous messages.
+ scoped_ptr<blink::WebInputEvent> ProcessMessage(const InputMessage& message);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputMessageProcessor);
+};
+
+} // namespace blimp
+
+#endif // BLIMP_NET_INPUT_MESSAGE_PROCESSOR_H_
diff --git a/blimp/net/input_message_unittest.cc b/blimp/net/input_message_unittest.cc
new file mode 100644
index 0000000..9b9d3d0
--- /dev/null
+++ b/blimp/net/input_message_unittest.cc
@@ -0,0 +1,133 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "blimp/common/proto/blimp_message.pb.h"
+#include "blimp/common/proto/input.pb.h"
+#include "blimp/net/blimp_message_processor.h"
+#include "blimp/net/input_message_generator.h"
+#include "blimp/net/input_message_processor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebGestureDevice.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace blimp {
+namespace {
+
+void ValidateWebInputEventRoundTripping(const blink::WebInputEvent& event) {
+ InputMessageGenerator generator;
+ InputMessageProcessor processor;
+
+ scoped_ptr<BlimpMessage> proto = generator.GenerateMessage(event);
+ EXPECT_NE(nullptr, proto.get());
+ EXPECT_TRUE(proto->has_input());
+ EXPECT_EQ(BlimpMessage::INPUT, proto->type());
+
+ scoped_ptr<blink::WebInputEvent> new_event = processor.ProcessMessage(
+ proto->input());
+ EXPECT_NE(nullptr, new_event.get());
+
+ EXPECT_EQ(event.size, new_event->size);
+ EXPECT_EQ(0, memcmp(&event, new_event.get(), event.size));
+}
+
+blink::WebGestureEvent BuildBaseTestEvent() {
+ blink::WebGestureEvent event;
+ event.timeStampSeconds = 1.23;
+ event.x = 2;
+ event.y = 3;
+ event.globalX = 4;
+ event.globalY = 5;
+ event.sourceDevice = blink::WebGestureDevice::WebGestureDeviceTouchscreen;
+ return event;
+}
+
+} // namespace
+
+TEST(InputMessageTest, TestGestureScrollBeginRoundTrip) {
+ blink::WebGestureEvent event = BuildBaseTestEvent();
+ event.type = blink::WebInputEvent::Type::GestureScrollBegin;
+ event.data.scrollBegin.deltaXHint = 2.34f;
+ event.data.scrollBegin.deltaYHint = 3.45f;
+ event.data.scrollBegin.targetViewport = true;
+ ValidateWebInputEventRoundTripping(event);
+}
+
+TEST(InputMessageTest, TestGestureScrollEndRoundTrip) {
+ blink::WebGestureEvent event = BuildBaseTestEvent();
+ event.type = blink::WebInputEvent::Type::GestureScrollEnd;
+ ValidateWebInputEventRoundTripping(event);
+}
+
+TEST(InputMessageTest, TestGestureScrollUpdateRoundTrip) {
+ blink::WebGestureEvent event = BuildBaseTestEvent();
+ event.type = blink::WebInputEvent::Type::GestureScrollUpdate;
+ event.data.scrollUpdate.deltaX = 2.34f;
+ event.data.scrollUpdate.deltaY = 3.45f;
+ event.data.scrollUpdate.velocityX = 4.56f;
+ event.data.scrollUpdate.velocityY = 5.67f;
+ event.data.scrollUpdate.previousUpdateInSequencePrevented = true;
+ event.data.scrollUpdate.preventPropagation = true;
+ event.data.scrollUpdate.inertial = true;
+ ValidateWebInputEventRoundTripping(event);
+}
+
+TEST(InputMessageTest, TestGestureFlingStartRoundTrip) {
+ blink::WebGestureEvent event = BuildBaseTestEvent();
+ event.type = blink::WebInputEvent::Type::GestureFlingStart;
+ event.data.flingStart.velocityX = 2.34f;
+ event.data.flingStart.velocityY = 3.45f;
+ event.data.flingStart.targetViewport = true;
+ ValidateWebInputEventRoundTripping(event);
+}
+
+TEST(InputMessageTest, TestGestureFlingCancelRoundTrip) {
+ blink::WebGestureEvent event = BuildBaseTestEvent();
+ event.type = blink::WebInputEvent::Type::GestureFlingCancel;
+ event.data.flingCancel.preventBoosting = true;
+ ValidateWebInputEventRoundTripping(event);
+}
+
+TEST(InputMessageTest, TestGestureTapRoundTrip) {
+ blink::WebGestureEvent event = BuildBaseTestEvent();
+ event.type = blink::WebGestureEvent::Type::GestureTap;
+ event.data.tap.tapCount = 3;
+ event.data.tap.width = 2.34f;
+ event.data.tap.height = 3.45f;
+ ValidateWebInputEventRoundTripping(event);
+}
+
+TEST(InputMessageTest, TestGesturePinchBeginRoundTrip) {
+ blink::WebGestureEvent event = BuildBaseTestEvent();
+ event.type = blink::WebInputEvent::Type::GesturePinchBegin;
+ ValidateWebInputEventRoundTripping(event);
+}
+
+TEST(InputMessageTest, TestGesturePinchEndRoundTrip) {
+ blink::WebGestureEvent event = BuildBaseTestEvent();
+ event.type = blink::WebInputEvent::Type::GesturePinchEnd;
+ ValidateWebInputEventRoundTripping(event);
+}
+
+TEST(InputMessageTest, TestGesturePinchUpdateRoundTrip) {
+ blink::WebGestureEvent event = BuildBaseTestEvent();
+ event.type = blink::WebInputEvent::Type::GesturePinchUpdate;
+ event.data.pinchUpdate.zoomDisabled = true;
+ event.data.pinchUpdate.scale = 2.34f;
+ ValidateWebInputEventRoundTripping(event);
+}
+
+TEST(InputMessageTest, TestUnsupportedInputEventSerializationFails) {
+ // We currently do not support WebMouseWheelEvents. If that changes update
+ // this test.
+ blink::WebMouseWheelEvent event;
+ event.type = blink::WebInputEvent::Type::MouseWheel;
+ InputMessageGenerator generator;
+ EXPECT_EQ(nullptr, generator.GenerateMessage(event).get());
+}
+
+} // namespace blimp