OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "base/command_line.h" | |
6 #include "base/synchronization/waitable_event.h" | |
7 #include "base/threading/platform_thread.h" | |
8 #include "content/browser/device_sensors/data_fetcher_shared_memory.h" | |
9 #include "content/browser/device_sensors/device_inertial_sensor_service.h" | |
10 #include "content/common/device_sensors/device_light_hardware_buffer.h" | |
11 #include "content/common/device_sensors/device_motion_hardware_buffer.h" | |
12 #include "content/common/device_sensors/device_orientation_hardware_buffer.h" | |
13 #include "content/public/browser/browser_thread.h" | |
14 #include "content/public/browser/web_contents.h" | |
15 #include "content/public/common/content_switches.h" | |
16 #include "content/public/test/content_browser_test.h" | |
17 #include "content/public/test/content_browser_test_utils.h" | |
18 #include "content/public/test/test_navigation_observer.h" | |
19 #include "content/public/test/test_utils.h" | |
20 #include "content/shell/browser/shell.h" | |
21 #include "content/shell/browser/shell_javascript_dialog_manager.h" | |
22 | |
23 namespace content { | |
24 | |
25 namespace { | |
26 | |
27 class FakeDataFetcher : public DataFetcherSharedMemory { | |
28 public: | |
29 FakeDataFetcher() | |
30 : started_orientation_(false, false), | |
31 stopped_orientation_(false, false), | |
32 started_motion_(false, false), | |
33 stopped_motion_(false, false), | |
34 started_light_(false, false), | |
35 stopped_light_(false, false), | |
36 sensor_data_available_(true) {} | |
37 ~FakeDataFetcher() override {} | |
38 | |
39 bool Start(ConsumerType consumer_type, void* buffer) override { | |
40 EXPECT_TRUE(buffer); | |
41 | |
42 switch (consumer_type) { | |
43 case CONSUMER_TYPE_MOTION: | |
44 { | |
45 DeviceMotionHardwareBuffer* motion_buffer = | |
46 static_cast<DeviceMotionHardwareBuffer*>(buffer); | |
47 if (sensor_data_available_) | |
48 UpdateMotion(motion_buffer); | |
49 SetMotionBufferReady(motion_buffer); | |
50 started_motion_.Signal(); | |
51 } | |
52 break; | |
53 case CONSUMER_TYPE_ORIENTATION: | |
54 { | |
55 DeviceOrientationHardwareBuffer* orientation_buffer = | |
56 static_cast<DeviceOrientationHardwareBuffer*>(buffer); | |
57 if (sensor_data_available_) | |
58 UpdateOrientation(orientation_buffer); | |
59 SetOrientationBufferReady(orientation_buffer); | |
60 started_orientation_.Signal(); | |
61 } | |
62 break; | |
63 case CONSUMER_TYPE_LIGHT: | |
64 { | |
65 DeviceLightHardwareBuffer* light_buffer = | |
66 static_cast<DeviceLightHardwareBuffer*>(buffer); | |
67 UpdateLight(light_buffer, | |
68 sensor_data_available_ | |
69 ? 100 | |
70 : std::numeric_limits<double>::infinity()); | |
71 started_light_.Signal(); | |
72 } | |
73 break; | |
74 default: | |
75 return false; | |
76 } | |
77 return true; | |
78 } | |
79 | |
80 bool Stop(ConsumerType consumer_type) override { | |
81 switch (consumer_type) { | |
82 case CONSUMER_TYPE_MOTION: | |
83 stopped_motion_.Signal(); | |
84 break; | |
85 case CONSUMER_TYPE_ORIENTATION: | |
86 stopped_orientation_.Signal(); | |
87 break; | |
88 case CONSUMER_TYPE_LIGHT: | |
89 stopped_light_.Signal(); | |
90 break; | |
91 default: | |
92 return false; | |
93 } | |
94 return true; | |
95 } | |
96 | |
97 void Fetch(unsigned consumer_bitmask) override { | |
98 FAIL() << "fetch should not be called"; | |
99 } | |
100 | |
101 FetcherType GetType() const override { return FETCHER_TYPE_DEFAULT; } | |
102 | |
103 void SetSensorDataAvailable(bool available) { | |
104 sensor_data_available_ = available; | |
105 } | |
106 | |
107 void SetMotionBufferReady(DeviceMotionHardwareBuffer* buffer) { | |
108 buffer->seqlock.WriteBegin(); | |
109 buffer->data.allAvailableSensorsAreActive = true; | |
110 buffer->seqlock.WriteEnd(); | |
111 } | |
112 | |
113 void SetOrientationBufferReady(DeviceOrientationHardwareBuffer* buffer) { | |
114 buffer->seqlock.WriteBegin(); | |
115 buffer->data.allAvailableSensorsAreActive = true; | |
116 buffer->seqlock.WriteEnd(); | |
117 } | |
118 | |
119 void UpdateMotion(DeviceMotionHardwareBuffer* buffer) { | |
120 buffer->seqlock.WriteBegin(); | |
121 buffer->data.accelerationX = 1; | |
122 buffer->data.hasAccelerationX = true; | |
123 buffer->data.accelerationY = 2; | |
124 buffer->data.hasAccelerationY = true; | |
125 buffer->data.accelerationZ = 3; | |
126 buffer->data.hasAccelerationZ = true; | |
127 | |
128 buffer->data.accelerationIncludingGravityX = 4; | |
129 buffer->data.hasAccelerationIncludingGravityX = true; | |
130 buffer->data.accelerationIncludingGravityY = 5; | |
131 buffer->data.hasAccelerationIncludingGravityY = true; | |
132 buffer->data.accelerationIncludingGravityZ = 6; | |
133 buffer->data.hasAccelerationIncludingGravityZ = true; | |
134 | |
135 buffer->data.rotationRateAlpha = 7; | |
136 buffer->data.hasRotationRateAlpha = true; | |
137 buffer->data.rotationRateBeta = 8; | |
138 buffer->data.hasRotationRateBeta = true; | |
139 buffer->data.rotationRateGamma = 9; | |
140 buffer->data.hasRotationRateGamma = true; | |
141 | |
142 buffer->data.interval = 100; | |
143 buffer->data.allAvailableSensorsAreActive = true; | |
144 buffer->seqlock.WriteEnd(); | |
145 } | |
146 | |
147 void UpdateOrientation(DeviceOrientationHardwareBuffer* buffer) { | |
148 buffer->seqlock.WriteBegin(); | |
149 buffer->data.alpha = 1; | |
150 buffer->data.hasAlpha = true; | |
151 buffer->data.beta = 2; | |
152 buffer->data.hasBeta = true; | |
153 buffer->data.gamma = 3; | |
154 buffer->data.hasGamma = true; | |
155 buffer->data.allAvailableSensorsAreActive = true; | |
156 buffer->seqlock.WriteEnd(); | |
157 } | |
158 | |
159 void UpdateLight(DeviceLightHardwareBuffer* buffer, double lux) { | |
160 buffer->seqlock.WriteBegin(); | |
161 buffer->data.value = lux; | |
162 buffer->seqlock.WriteEnd(); | |
163 } | |
164 | |
165 base::WaitableEvent started_orientation_; | |
166 base::WaitableEvent stopped_orientation_; | |
167 base::WaitableEvent started_motion_; | |
168 base::WaitableEvent stopped_motion_; | |
169 base::WaitableEvent started_light_; | |
170 base::WaitableEvent stopped_light_; | |
171 bool sensor_data_available_; | |
172 | |
173 private: | |
174 DISALLOW_COPY_AND_ASSIGN(FakeDataFetcher); | |
175 }; | |
176 | |
177 | |
178 class DeviceInertialSensorBrowserTest : public ContentBrowserTest { | |
179 public: | |
180 DeviceInertialSensorBrowserTest() | |
181 : fetcher_(nullptr), io_loop_finished_event_(false, false) {} | |
182 | |
183 void SetUpOnMainThread() override { | |
184 BrowserThread::PostTask( | |
185 BrowserThread::IO, FROM_HERE, | |
186 base::Bind(&DeviceInertialSensorBrowserTest::SetUpOnIOThread, this)); | |
187 io_loop_finished_event_.Wait(); | |
188 } | |
189 | |
190 void SetUpOnIOThread() { | |
191 fetcher_ = new FakeDataFetcher(); | |
192 DeviceInertialSensorService::GetInstance()-> | |
193 SetDataFetcherForTesting(fetcher_); | |
194 io_loop_finished_event_.Signal(); | |
195 } | |
196 | |
197 void DelayAndQuit(base::TimeDelta delay) { | |
198 base::PlatformThread::Sleep(delay); | |
199 base::MessageLoop::current()->QuitWhenIdle(); | |
200 } | |
201 | |
202 void WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta delay) { | |
203 ShellJavaScriptDialogManager* dialog_manager = | |
204 static_cast<ShellJavaScriptDialogManager*>( | |
205 shell()->GetJavaScriptDialogManager(shell()->web_contents())); | |
206 | |
207 scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner(); | |
208 dialog_manager->set_dialog_request_callback( | |
209 base::Bind(&DeviceInertialSensorBrowserTest::DelayAndQuit, this, | |
210 delay)); | |
211 runner->Run(); | |
212 } | |
213 | |
214 void EnableExperimentalFeatures() { | |
215 // TODO(riju): remove when the DeviceLight feature goes stable. | |
216 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | |
217 if (!cmd_line->HasSwitch(switches::kEnableExperimentalWebPlatformFeatures)) | |
218 cmd_line->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures); | |
219 } | |
220 | |
221 FakeDataFetcher* fetcher_; | |
222 | |
223 private: | |
224 base::WaitableEvent io_loop_finished_event_; | |
225 }; | |
226 | |
227 IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, OrientationTest) { | |
228 // The test page will register an event handler for orientation events, | |
229 // expects to get an event with fake values, then removes the event | |
230 // handler and navigates to #pass. | |
231 GURL test_url = GetTestUrl("device_sensors", "device_orientation_test.html"); | |
232 NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2); | |
233 | |
234 EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref()); | |
235 fetcher_->started_orientation_.Wait(); | |
236 fetcher_->stopped_orientation_.Wait(); | |
237 } | |
238 | |
239 IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, LightTest) { | |
240 // The test page will register an event handler for light events, | |
241 // expects to get an event with fake values, then removes the event | |
242 // handler and navigates to #pass. | |
243 EnableExperimentalFeatures(); | |
244 GURL test_url = GetTestUrl("device_sensors", "device_light_test.html"); | |
245 NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2); | |
246 | |
247 EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref()); | |
248 fetcher_->started_light_.Wait(); | |
249 fetcher_->stopped_light_.Wait(); | |
250 } | |
251 | |
252 IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, MotionTest) { | |
253 // The test page will register an event handler for motion events, | |
254 // expects to get an event with fake values, then removes the event | |
255 // handler and navigates to #pass. | |
256 GURL test_url = GetTestUrl("device_sensors", "device_motion_test.html"); | |
257 NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2); | |
258 | |
259 EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref()); | |
260 fetcher_->started_motion_.Wait(); | |
261 fetcher_->stopped_motion_.Wait(); | |
262 } | |
263 | |
264 IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, | |
265 LightOneOffInfintyTest) { | |
266 // The test page registers an event handler for light events and expects | |
267 // to get an event with value equal to infinity, because no sensor data can | |
268 // be provided. | |
269 EnableExperimentalFeatures(); | |
270 fetcher_->SetSensorDataAvailable(false); | |
271 GURL test_url = GetTestUrl("device_sensors", | |
272 "device_light_infinity_test.html"); | |
273 NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2); | |
274 | |
275 EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref()); | |
276 fetcher_->started_light_.Wait(); | |
277 fetcher_->stopped_light_.Wait(); | |
278 } | |
279 | |
280 IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, OrientationNullTest) { | |
281 // The test page registers an event handler for orientation events and | |
282 // expects to get an event with null values, because no sensor data can be | |
283 // provided. | |
284 fetcher_->SetSensorDataAvailable(false); | |
285 GURL test_url = GetTestUrl("device_sensors", | |
286 "device_orientation_null_test.html"); | |
287 NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2); | |
288 | |
289 EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref()); | |
290 fetcher_->started_orientation_.Wait(); | |
291 fetcher_->stopped_orientation_.Wait(); | |
292 } | |
293 | |
294 IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, MotionNullTest) { | |
295 // The test page registers an event handler for motion events and | |
296 // expects to get an event with null values, because no sensor data can be | |
297 // provided. | |
298 fetcher_->SetSensorDataAvailable(false); | |
299 GURL test_url = GetTestUrl("device_sensors", | |
300 "device_motion_null_test.html"); | |
301 NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2); | |
302 | |
303 EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref()); | |
304 fetcher_->started_motion_.Wait(); | |
305 fetcher_->stopped_motion_.Wait(); | |
306 } | |
307 | |
308 IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, | |
309 DISABLED_NullTestWithAlert) { | |
310 // The test page registers an event handlers for motion/orientation events | |
311 // and expects to get events with null values. The test raises a modal alert | |
312 // dialog with a delay to test that the one-off null-events still propagate | |
313 // to window after the alert is dismissed and the callbacks are invoked which | |
314 // eventually navigate to #pass. | |
315 fetcher_->SetSensorDataAvailable(false); | |
316 TestNavigationObserver same_tab_observer(shell()->web_contents(), 2); | |
317 | |
318 GURL test_url = GetTestUrl("device_sensors", | |
319 "device_sensors_null_test_with_alert.html"); | |
320 shell()->LoadURL(test_url); | |
321 | |
322 // TODO(timvolodine): investigate if it is possible to test this without | |
323 // delay, crbug.com/360044. | |
324 WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(500)); | |
325 | |
326 fetcher_->started_motion_.Wait(); | |
327 fetcher_->stopped_motion_.Wait(); | |
328 fetcher_->started_orientation_.Wait(); | |
329 fetcher_->stopped_orientation_.Wait(); | |
330 same_tab_observer.Wait(); | |
331 EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref()); | |
332 } | |
333 | |
334 } // namespace | |
335 | |
336 } // namespace content | |
OLD | NEW |