device_inertial_sensor_browsertest.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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/synchronization/waitable_event.h"
6#include "base/threading/platform_thread.h"
7#include "content/browser/device_sensors/data_fetcher_shared_memory.h"
8#include "content/browser/device_sensors/device_inertial_sensor_service.h"
9#include "content/common/device_sensors/device_motion_hardware_buffer.h"
10#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
11#include "content/public/browser/browser_thread.h"
12#include "content/public/browser/web_contents.h"
13#include "content/public/test/content_browser_test.h"
14#include "content/public/test/content_browser_test_utils.h"
15#include "content/public/test/test_navigation_observer.h"
16#include "content/public/test/test_utils.h"
17#include "content/shell/browser/shell.h"
18#include "content/shell/browser/shell_javascript_dialog_manager.h"
19
20namespace content {
21
22namespace {
23
24class FakeDataFetcher : public DataFetcherSharedMemory {
25 public:
26  FakeDataFetcher()
27      : started_orientation_(false, false),
28        stopped_orientation_(false, false),
29        started_motion_(false, false),
30        stopped_motion_(false, false),
31        sensor_data_available_(true) {
32  }
33  virtual ~FakeDataFetcher() { }
34
35  virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE {
36    EXPECT_TRUE(buffer);
37
38    switch (consumer_type) {
39      case CONSUMER_TYPE_MOTION:
40        {
41          DeviceMotionHardwareBuffer* motion_buffer =
42              static_cast<DeviceMotionHardwareBuffer*>(buffer);
43          if (sensor_data_available_)
44            UpdateMotion(motion_buffer);
45          SetMotionBufferReady(motion_buffer);
46          started_motion_.Signal();
47        }
48        break;
49      case CONSUMER_TYPE_ORIENTATION:
50        {
51          DeviceOrientationHardwareBuffer* orientation_buffer =
52              static_cast<DeviceOrientationHardwareBuffer*>(buffer);
53          if (sensor_data_available_)
54            UpdateOrientation(orientation_buffer);
55          SetOrientationBufferReady(orientation_buffer);
56          started_orientation_.Signal();
57        }
58        break;
59      default:
60        return false;
61    }
62    return true;
63  }
64
65  virtual bool Stop(ConsumerType consumer_type) OVERRIDE {
66    switch (consumer_type) {
67      case CONSUMER_TYPE_MOTION:
68        stopped_motion_.Signal();
69        break;
70      case CONSUMER_TYPE_ORIENTATION:
71        stopped_orientation_.Signal();
72        break;
73      default:
74        return false;
75    }
76    return true;
77  }
78
79  virtual void Fetch(unsigned consumer_bitmask) OVERRIDE {
80    FAIL() << "fetch should not be called";
81  }
82
83  virtual FetcherType GetType() const OVERRIDE {
84    return FETCHER_TYPE_DEFAULT;
85  }
86
87  void SetSensorDataAvailable(bool available) {
88    sensor_data_available_ = available;
89  }
90
91  void SetMotionBufferReady(DeviceMotionHardwareBuffer* buffer) {
92    buffer->seqlock.WriteBegin();
93    buffer->data.allAvailableSensorsAreActive = true;
94    buffer->seqlock.WriteEnd();
95  }
96
97  void SetOrientationBufferReady(DeviceOrientationHardwareBuffer* buffer) {
98    buffer->seqlock.WriteBegin();
99    buffer->data.allAvailableSensorsAreActive = true;
100    buffer->seqlock.WriteEnd();
101  }
102
103  void UpdateMotion(DeviceMotionHardwareBuffer* buffer) {
104    buffer->seqlock.WriteBegin();
105    buffer->data.accelerationX = 1;
106    buffer->data.hasAccelerationX = true;
107    buffer->data.accelerationY = 2;
108    buffer->data.hasAccelerationY = true;
109    buffer->data.accelerationZ = 3;
110    buffer->data.hasAccelerationZ = true;
111
112    buffer->data.accelerationIncludingGravityX = 4;
113    buffer->data.hasAccelerationIncludingGravityX = true;
114    buffer->data.accelerationIncludingGravityY = 5;
115    buffer->data.hasAccelerationIncludingGravityY = true;
116    buffer->data.accelerationIncludingGravityZ = 6;
117    buffer->data.hasAccelerationIncludingGravityZ = true;
118
119    buffer->data.rotationRateAlpha = 7;
120    buffer->data.hasRotationRateAlpha = true;
121    buffer->data.rotationRateBeta = 8;
122    buffer->data.hasRotationRateBeta = true;
123    buffer->data.rotationRateGamma = 9;
124    buffer->data.hasRotationRateGamma = true;
125
126    buffer->data.interval = 100;
127    buffer->data.allAvailableSensorsAreActive = true;
128    buffer->seqlock.WriteEnd();
129  }
130
131  void UpdateOrientation(DeviceOrientationHardwareBuffer* buffer) {
132    buffer->seqlock.WriteBegin();
133    buffer->data.alpha = 1;
134    buffer->data.hasAlpha = true;
135    buffer->data.beta = 2;
136    buffer->data.hasBeta = true;
137    buffer->data.gamma = 3;
138    buffer->data.hasGamma = true;
139    buffer->data.allAvailableSensorsAreActive = true;
140    buffer->seqlock.WriteEnd();
141  }
142
143  base::WaitableEvent started_orientation_;
144  base::WaitableEvent stopped_orientation_;
145  base::WaitableEvent started_motion_;
146  base::WaitableEvent stopped_motion_;
147  bool sensor_data_available_;
148
149 private:
150  DISALLOW_COPY_AND_ASSIGN(FakeDataFetcher);
151};
152
153
154class DeviceInertialSensorBrowserTest : public ContentBrowserTest  {
155 public:
156  DeviceInertialSensorBrowserTest()
157      : fetcher_(NULL),
158        io_loop_finished_event_(false, false) {
159  }
160
161  virtual void SetUpOnMainThread() OVERRIDE {
162    BrowserThread::PostTask(
163        BrowserThread::IO, FROM_HERE,
164        base::Bind(&DeviceInertialSensorBrowserTest::SetUpOnIOThread, this));
165    io_loop_finished_event_.Wait();
166  }
167
168  void SetUpOnIOThread() {
169    fetcher_ = new FakeDataFetcher();
170    DeviceInertialSensorService::GetInstance()->
171        SetDataFetcherForTesting(fetcher_);
172    io_loop_finished_event_.Signal();
173  }
174
175  void DelayAndQuit(base::TimeDelta delay) {
176    base::PlatformThread::Sleep(delay);
177    base::MessageLoop::current()->QuitWhenIdle();
178  }
179
180  void WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta delay) {
181    ShellJavaScriptDialogManager* dialog_manager=
182        static_cast<ShellJavaScriptDialogManager*>(
183            shell()->GetJavaScriptDialogManager());
184
185    scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
186    dialog_manager->set_dialog_request_callback(
187        base::Bind(&DeviceInertialSensorBrowserTest::DelayAndQuit, this,
188            delay));
189    runner->Run();
190  }
191
192  FakeDataFetcher* fetcher_;
193
194 private:
195  base::WaitableEvent io_loop_finished_event_;
196};
197
198
199IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, OrientationTest) {
200  // The test page will register an event handler for orientation events,
201  // expects to get an event with fake values, then removes the event
202  // handler and navigates to #pass.
203  GURL test_url = GetTestUrl(
204      "device_orientation", "device_orientation_test.html");
205  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
206
207  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
208  fetcher_->started_orientation_.Wait();
209  fetcher_->stopped_orientation_.Wait();
210}
211
212IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, MotionTest) {
213  // The test page will register an event handler for motion events,
214  // expects to get an event with fake values, then removes the event
215  // handler and navigates to #pass.
216  GURL test_url = GetTestUrl(
217      "device_orientation", "device_motion_test.html");
218  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
219
220  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
221  fetcher_->started_motion_.Wait();
222  fetcher_->stopped_motion_.Wait();
223}
224
225// Flaking in the android try bot. See http://crbug.com/360578.
226#if defined(OS_ANDROID)
227#define MAYBE_OrientationNullTestWithAlert DISABLED_OrientationNullTestWithAlert
228#else
229#define MAYBE_OrientationNullTestWithAlert OrientationNullTestWithAlert
230#endif
231IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
232    MAYBE_OrientationNullTestWithAlert) {
233  // The test page will register an event handler for orientation events,
234  // expects to get an event with null values. The test raises a modal alert
235  // dialog with a delay to test that the one-off null-event still propagates
236  // to window after the alert is dismissed and the callback is invoked which
237  // navigates to #pass.
238  fetcher_->SetSensorDataAvailable(false);
239  TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
240
241  GURL test_url = GetTestUrl(
242      "device_orientation", "device_orientation_null_test_with_alert.html");
243  shell()->LoadURL(test_url);
244
245  // TODO(timvolodine): investigate if it is possible to test this without
246  // delay, crbug.com/360044.
247  WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(1000));
248
249  fetcher_->started_orientation_.Wait();
250  fetcher_->stopped_orientation_.Wait();
251  same_tab_observer.Wait();
252  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
253}
254
255// Flaking in the android try bot. See http://crbug.com/360578.
256#if defined(OS_ANDROID)
257#define MAYBE_MotionNullTestWithAlert DISABLED_MotionNullTestWithAlert
258#else
259#define MAYBE_MotionNullTestWithAlert MotionNullTestWithAlert
260#endif
261IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
262    MAYBE_MotionNullTestWithAlert) {
263  // The test page will register an event handler for motion events,
264  // expects to get an event with null values. The test raises a modal alert
265  // dialog with a delay to test that the one-off null-event still propagates
266  // to window after the alert is dismissed and the callback is invoked which
267  // navigates to #pass.
268  fetcher_->SetSensorDataAvailable(false);
269  TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
270
271  GURL test_url = GetTestUrl(
272      "device_orientation", "device_motion_null_test_with_alert.html");
273  shell()->LoadURL(test_url);
274
275  // TODO(timvolodine): investigate if it is possible to test this without
276  // delay, crbug.com/360044.
277  WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(1000));
278
279  fetcher_->started_motion_.Wait();
280  fetcher_->stopped_motion_.Wait();
281  same_tab_observer.Wait();
282  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
283}
284
285}  //  namespace
286
287}  //  namespace content
288