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