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/location.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "content/common/device_sensors/device_motion_hardware_buffer.h"
13 #include "content/public/test/test_utils.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/WebKit/public/platform/modules/device_orientation/WebDeviceMotionListener.h"
19 class MockDeviceMotionListener
: public blink::WebDeviceMotionListener
{
21 MockDeviceMotionListener()
22 : did_change_device_motion_(false), number_of_events_(0) {
23 memset(&data_
, 0, sizeof(data_
));
25 virtual ~MockDeviceMotionListener() { }
27 virtual void didChangeDeviceMotion(
28 const blink::WebDeviceMotionData
& data
) override
{
29 memcpy(&data_
, &data
, sizeof(data
));
30 did_change_device_motion_
= true;
34 bool did_change_device_motion() const {
35 return did_change_device_motion_
;
38 int number_of_events() const { return number_of_events_
; }
40 const blink::WebDeviceMotionData
& data() const {
45 bool did_change_device_motion_
;
46 int number_of_events_
;
47 blink::WebDeviceMotionData data_
;
49 DISALLOW_COPY_AND_ASSIGN(MockDeviceMotionListener
);
52 class DeviceMotionEventPumpForTesting
: public DeviceMotionEventPump
{
54 DeviceMotionEventPumpForTesting()
55 : DeviceMotionEventPump(0), stop_on_fire_event_(true) {}
56 ~DeviceMotionEventPumpForTesting() override
{}
58 void set_stop_on_fire_event(bool stop_on_fire_event
) {
59 stop_on_fire_event_
= stop_on_fire_event
;
62 bool stop_on_fire_event() { return stop_on_fire_event_
; }
64 int pump_delay_microseconds() const { return pump_delay_microseconds_
; }
66 void OnDidStart(base::SharedMemoryHandle renderer_handle
) {
67 DeviceMotionEventPump::OnDidStart(renderer_handle
);
69 void SendStartMessage() override
{}
70 void SendStopMessage() override
{}
71 void FireEvent() override
{
72 DeviceMotionEventPump::FireEvent();
73 if (stop_on_fire_event_
) {
75 base::MessageLoop::current()->QuitWhenIdle();
80 bool stop_on_fire_event_
;
82 DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPumpForTesting
);
85 class DeviceMotionEventPumpTest
: public testing::Test
{
87 DeviceMotionEventPumpTest() {
88 EXPECT_TRUE(shared_memory_
.CreateAndMapAnonymous(
89 sizeof(DeviceMotionHardwareBuffer
)));
93 void SetUp() override
{
94 const DeviceMotionHardwareBuffer
* null_buffer
= nullptr;
95 listener_
.reset(new MockDeviceMotionListener
);
96 motion_pump_
.reset(new DeviceMotionEventPumpForTesting
);
97 buffer_
= static_cast<DeviceMotionHardwareBuffer
*>(shared_memory_
.memory());
98 ASSERT_NE(null_buffer
, buffer_
);
99 memset(buffer_
, 0, sizeof(DeviceMotionHardwareBuffer
));
100 ASSERT_TRUE(shared_memory_
.ShareToProcess(base::GetCurrentProcessHandle(),
104 void InitBuffer(bool allAvailableSensorsActive
) {
105 blink::WebDeviceMotionData
& data
= buffer_
->data
;
106 data
.accelerationX
= 1;
107 data
.hasAccelerationX
= true;
108 data
.accelerationY
= 2;
109 data
.hasAccelerationY
= true;
110 data
.accelerationZ
= 3;
111 data
.hasAccelerationZ
= true;
112 data
.allAvailableSensorsAreActive
= allAvailableSensorsActive
;
115 MockDeviceMotionListener
* listener() { return listener_
.get(); }
116 DeviceMotionEventPumpForTesting
* motion_pump() { return motion_pump_
.get(); }
117 base::SharedMemoryHandle
handle() { return handle_
; }
120 scoped_ptr
<MockDeviceMotionListener
> listener_
;
121 scoped_ptr
<DeviceMotionEventPumpForTesting
> motion_pump_
;
122 base::SharedMemoryHandle handle_
;
123 base::SharedMemory shared_memory_
;
124 DeviceMotionHardwareBuffer
* buffer_
;
126 DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPumpTest
);
129 TEST_F(DeviceMotionEventPumpTest
, DidStartPolling
) {
130 base::MessageLoopForUI loop
;
134 motion_pump()->Start(listener());
135 motion_pump()->OnDidStart(handle());
137 base::MessageLoop::current()->Run();
139 const blink::WebDeviceMotionData
& received_data
= listener()->data();
140 EXPECT_TRUE(listener()->did_change_device_motion());
141 EXPECT_TRUE(received_data
.hasAccelerationX
);
142 EXPECT_EQ(1, static_cast<double>(received_data
.accelerationX
));
143 EXPECT_TRUE(received_data
.hasAccelerationX
);
144 EXPECT_EQ(2, static_cast<double>(received_data
.accelerationY
));
145 EXPECT_TRUE(received_data
.hasAccelerationY
);
146 EXPECT_EQ(3, static_cast<double>(received_data
.accelerationZ
));
147 EXPECT_TRUE(received_data
.hasAccelerationZ
);
148 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityX
);
149 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityY
);
150 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityZ
);
151 EXPECT_FALSE(received_data
.hasRotationRateAlpha
);
152 EXPECT_FALSE(received_data
.hasRotationRateBeta
);
153 EXPECT_FALSE(received_data
.hasRotationRateGamma
);
156 TEST_F(DeviceMotionEventPumpTest
, DidStartPollingNotAllSensorsActive
) {
157 base::MessageLoopForUI loop
;
161 motion_pump()->Start(listener());
162 motion_pump()->OnDidStart(handle());
164 base::MessageLoop::current()->Run();
166 const blink::WebDeviceMotionData
& received_data
= listener()->data();
167 // No change in device motion because allAvailableSensorsAreActive is false.
168 EXPECT_FALSE(listener()->did_change_device_motion());
169 EXPECT_FALSE(received_data
.hasAccelerationX
);
170 EXPECT_FALSE(received_data
.hasAccelerationX
);
171 EXPECT_FALSE(received_data
.hasAccelerationY
);
172 EXPECT_FALSE(received_data
.hasAccelerationZ
);
173 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityX
);
174 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityY
);
175 EXPECT_FALSE(received_data
.hasAccelerationIncludingGravityZ
);
176 EXPECT_FALSE(received_data
.hasRotationRateAlpha
);
177 EXPECT_FALSE(received_data
.hasRotationRateBeta
);
178 EXPECT_FALSE(received_data
.hasRotationRateGamma
);
181 // Confirm that the frequency of pumping events is not greater than 60Hz. A rate
182 // above 60Hz would allow for the detection of keystrokes (crbug.com/421691)
183 TEST_F(DeviceMotionEventPumpTest
, PumpThrottlesEventRate
) {
184 // Confirm that the delay for pumping events is 60 Hz.
185 EXPECT_GE(60, base::Time::kMicrosecondsPerSecond
/
186 motion_pump()->pump_delay_microseconds());
188 base::MessageLoopForUI loop
;
192 motion_pump()->set_stop_on_fire_event(false);
193 motion_pump()->Start(listener());
194 motion_pump()->OnDidStart(handle());
196 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
197 FROM_HERE
, base::MessageLoop::QuitClosure(),
198 base::TimeDelta::FromMilliseconds(100));
199 base::MessageLoop::current()->Run();
200 motion_pump()->Stop();
202 // Check that the blink::WebDeviceMotionListener does not receive excess
204 EXPECT_TRUE(listener()->did_change_device_motion());
205 EXPECT_GE(6, listener()->number_of_events());
208 } // namespace content