1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "device_motion_event_pump.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "content/common/device_sensors/device_motion_hardware_buffer.h"
11 #include "content/public/test/test_utils.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebDeviceMotionListener.h"
17 class MockDeviceMotionListener
: public blink::WebDeviceMotionListener
{
19 MockDeviceMotionListener()
20 : did_change_device_motion_(false), number_of_events_(0) {
21 memset(&data_
, 0, sizeof(data_
));
23 virtual ~MockDeviceMotionListener() { }
25 virtual void didChangeDeviceMotion(
26 const blink::WebDeviceMotionData
& data
) override
{
27 memcpy(&data_
, &data
, sizeof(data
));
28 did_change_device_motion_
= true;
32 bool did_change_device_motion() const {
33 return did_change_device_motion_
;
36 int number_of_events() const { return number_of_events_
; }
38 const blink::WebDeviceMotionData
& data() const {
43 bool did_change_device_motion_
;
44 int number_of_events_
;
45 blink::WebDeviceMotionData data_
;
47 DISALLOW_COPY_AND_ASSIGN(MockDeviceMotionListener
);
50 class DeviceMotionEventPumpForTesting
: public DeviceMotionEventPump
{
52 DeviceMotionEventPumpForTesting()
53 : DeviceMotionEventPump(0), stop_on_fire_event_(true) {}
54 ~DeviceMotionEventPumpForTesting() override
{}
56 void set_stop_on_fire_event(bool stop_on_fire_event
) {
57 stop_on_fire_event_
= stop_on_fire_event
;
60 bool stop_on_fire_event() { return stop_on_fire_event_
; }
62 int pump_delay_microseconds() const { return pump_delay_microseconds_
; }
64 void OnDidStart(base::SharedMemoryHandle renderer_handle
) {
65 DeviceMotionEventPump::OnDidStart(renderer_handle
);
67 void SendStartMessage() override
{}
68 void SendStopMessage() override
{}
69 void FireEvent() override
{
70 DeviceMotionEventPump::FireEvent();
71 if (stop_on_fire_event_
) {
73 base::MessageLoop::current()->QuitWhenIdle();
78 bool stop_on_fire_event_
;
80 DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPumpForTesting
);
83 class DeviceMotionEventPumpTest
: public testing::Test
{
85 DeviceMotionEventPumpTest() {
86 EXPECT_TRUE(shared_memory_
.CreateAndMapAnonymous(
87 sizeof(DeviceMotionHardwareBuffer
)));
91 void SetUp() override
{
92 const DeviceMotionHardwareBuffer
* null_buffer
= nullptr;
93 listener_
.reset(new MockDeviceMotionListener
);
94 motion_pump_
.reset(new DeviceMotionEventPumpForTesting
);
95 buffer_
= static_cast<DeviceMotionHardwareBuffer
*>(shared_memory_
.memory());
96 ASSERT_NE(null_buffer
, buffer_
);
97 memset(buffer_
, 0, sizeof(DeviceMotionHardwareBuffer
));
98 ASSERT_TRUE(shared_memory_
.ShareToProcess(base::GetCurrentProcessHandle(),
102 void InitBuffer(bool allAvailableSensorsActive
) {
103 blink::WebDeviceMotionData
& data
= buffer_
->data
;
104 data
.accelerationX
= 1;
105 data
.hasAccelerationX
= true;
106 data
.accelerationY
= 2;
107 data
.hasAccelerationY
= true;
108 data
.accelerationZ
= 3;
109 data
.hasAccelerationZ
= true;
110 data
.allAvailableSensorsAreActive
= allAvailableSensorsActive
;
113 MockDeviceMotionListener
* listener() { return listener_
.get(); }
114 DeviceMotionEventPumpForTesting
* motion_pump() { return motion_pump_
.get(); }
115 base::SharedMemoryHandle
handle() { return handle_
; }
118 scoped_ptr
<MockDeviceMotionListener
> listener_
;
119 scoped_ptr
<DeviceMotionEventPumpForTesting
> motion_pump_
;
120 base::SharedMemoryHandle handle_
;
121 base::SharedMemory shared_memory_
;
122 DeviceMotionHardwareBuffer
* buffer_
;
124 DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPumpTest
);
127 TEST_F(DeviceMotionEventPumpTest
, DidStartPolling
) {
128 base::MessageLoopForUI loop
;
132 motion_pump()->Start(listener());
133 motion_pump()->OnDidStart(handle());
135 base::MessageLoop::current()->Run();
137 const blink::WebDeviceMotionData
& received_data
= listener()->data();
138 EXPECT_TRUE(listener()->did_change_device_motion());
139 EXPECT_TRUE(received_data
.hasAccelerationX
);
140 EXPECT_EQ(1, static_cast<double>(received_data
.accelerationX
));
141 EXPECT_TRUE(received_data
.hasAccelerationX
);
142 EXPECT_EQ(2, static_cast<double>(received_data
.accelerationY
));
143 EXPECT_TRUE(received_data
.hasAccelerationY
);
144 EXPECT_EQ(3, static_cast<double>(received_data
.accelerationZ
));
145 EXPECT_TRUE(received_data
.hasAccelerationZ
);
146 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityX
);
147 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityY
);
148 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityZ
);
149 EXPECT_FALSE(received_data
.hasRotationRateAlpha
);
150 EXPECT_FALSE(received_data
.hasRotationRateBeta
);
151 EXPECT_FALSE(received_data
.hasRotationRateGamma
);
154 TEST_F(DeviceMotionEventPumpTest
, DidStartPollingNotAllSensorsActive
) {
155 base::MessageLoopForUI loop
;
159 motion_pump()->Start(listener());
160 motion_pump()->OnDidStart(handle());
162 base::MessageLoop::current()->Run();
164 const blink::WebDeviceMotionData
& received_data
= listener()->data();
165 // No change in device motion because allAvailableSensorsAreActive is false.
166 EXPECT_FALSE(listener()->did_change_device_motion());
167 EXPECT_FALSE(received_data
.hasAccelerationX
);
168 EXPECT_FALSE(received_data
.hasAccelerationX
);
169 EXPECT_FALSE(received_data
.hasAccelerationY
);
170 EXPECT_FALSE(received_data
.hasAccelerationZ
);
171 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityX
);
172 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityY
);
173 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityZ
);
174 EXPECT_FALSE(received_data
.hasRotationRateAlpha
);
175 EXPECT_FALSE(received_data
.hasRotationRateBeta
);
176 EXPECT_FALSE(received_data
.hasRotationRateGamma
);
179 // Confirm that the frequency of pumping events is not greater than 60Hz. A rate
180 // above 60Hz would allow for the detection of keystrokes (crbug.com/421691)
181 TEST_F(DeviceMotionEventPumpTest
, PumpThrottlesEventRate
) {
182 // Confirm that the delay for pumping events is 60 Hz.
183 EXPECT_GE(60, base::Time::kMicrosecondsPerSecond
/
184 motion_pump()->pump_delay_microseconds());
186 base::MessageLoopForUI loop
;
190 motion_pump()->set_stop_on_fire_event(false);
191 motion_pump()->Start(listener());
192 motion_pump()->OnDidStart(handle());
194 base::MessageLoop::current()->PostDelayedTask(
195 FROM_HERE
, base::MessageLoop::QuitClosure(),
196 base::TimeDelta::FromMilliseconds(100));
197 base::MessageLoop::current()->Run();
198 motion_pump()->Stop();
200 // Check that the blink::WebDeviceMotionListener does not receive excess
202 EXPECT_TRUE(listener()->did_change_device_motion());
203 EXPECT_GE(6, listener()->number_of_events());
206 } // namespace content