| 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 "device/geolocation/geolocation_provider_impl.h" |  | 
| 6 |  | 
| 7 #include <memory> |  | 
| 8 |  | 
| 9 #include "base/bind.h" |  | 
| 10 #include "base/bind_helpers.h" |  | 
| 11 #include "base/location.h" |  | 
| 12 #include "base/macros.h" |  | 
| 13 #include "base/memory/ptr_util.h" |  | 
| 14 #include "base/memory/ref_counted.h" |  | 
| 15 #include "base/run_loop.h" |  | 
| 16 #include "base/single_thread_task_runner.h" |  | 
| 17 #include "base/strings/string16.h" |  | 
| 18 #include "base/time/time.h" |  | 
| 19 #include "device/geolocation/access_token_store.h" |  | 
| 20 #include "device/geolocation/mock_location_arbitrator.h" |  | 
| 21 #include "testing/gmock/include/gmock/gmock.h" |  | 
| 22 #include "testing/gtest/include/gtest/gtest.h" |  | 
| 23 |  | 
| 24 using testing::MakeMatcher; |  | 
| 25 using testing::Matcher; |  | 
| 26 using testing::MatcherInterface; |  | 
| 27 using testing::MatchResultListener; |  | 
| 28 |  | 
| 29 namespace device { |  | 
| 30 |  | 
| 31 class LocationProviderForTestArbitrator : public GeolocationProviderImpl { |  | 
| 32  public: |  | 
| 33   LocationProviderForTestArbitrator() : mock_arbitrator_(NULL) {} |  | 
| 34   ~LocationProviderForTestArbitrator() override {} |  | 
| 35 |  | 
| 36   // Only valid for use on the geolocation thread. |  | 
| 37   MockLocationArbitrator* mock_arbitrator() const { |  | 
| 38     return mock_arbitrator_; |  | 
| 39   } |  | 
| 40 |  | 
| 41  protected: |  | 
| 42   // GeolocationProviderImpl implementation: |  | 
| 43   std::unique_ptr<LocationArbitrator> CreateArbitrator() override; |  | 
| 44 |  | 
| 45  private: |  | 
| 46   // An alias to the arbitrator stored in the super class, where it is owned. |  | 
| 47   MockLocationArbitrator* mock_arbitrator_; |  | 
| 48 }; |  | 
| 49 |  | 
| 50 std::unique_ptr<LocationArbitrator> |  | 
| 51 LocationProviderForTestArbitrator::CreateArbitrator() { |  | 
| 52   DCHECK(mock_arbitrator_ == NULL); |  | 
| 53   mock_arbitrator_ = new MockLocationArbitrator; |  | 
| 54   return base::WrapUnique(mock_arbitrator_); |  | 
| 55 } |  | 
| 56 |  | 
| 57 class GeolocationObserver { |  | 
| 58  public: |  | 
| 59   virtual ~GeolocationObserver() {} |  | 
| 60   virtual void OnLocationUpdate(const Geoposition& position) = 0; |  | 
| 61 }; |  | 
| 62 |  | 
| 63 class MockGeolocationObserver : public GeolocationObserver { |  | 
| 64  public: |  | 
| 65   MOCK_METHOD1(OnLocationUpdate, void(const Geoposition& position)); |  | 
| 66 }; |  | 
| 67 |  | 
| 68 class AsyncMockGeolocationObserver : public MockGeolocationObserver { |  | 
| 69  public: |  | 
| 70   void OnLocationUpdate(const Geoposition& position) override { |  | 
| 71     MockGeolocationObserver::OnLocationUpdate(position); |  | 
| 72     base::MessageLoop::current()->QuitWhenIdle(); |  | 
| 73   } |  | 
| 74 }; |  | 
| 75 |  | 
| 76 class MockGeolocationCallbackWrapper { |  | 
| 77  public: |  | 
| 78   MOCK_METHOD1(Callback, void(const Geoposition& position)); |  | 
| 79 }; |  | 
| 80 |  | 
| 81 class GeopositionEqMatcher |  | 
| 82     : public MatcherInterface<const Geoposition&> { |  | 
| 83  public: |  | 
| 84   explicit GeopositionEqMatcher(const Geoposition& expected) |  | 
| 85       : expected_(expected) {} |  | 
| 86 |  | 
| 87   bool MatchAndExplain(const Geoposition& actual, |  | 
| 88                        MatchResultListener* listener) const override { |  | 
| 89     return actual.latitude == expected_.latitude && |  | 
| 90            actual.longitude == expected_.longitude && |  | 
| 91            actual.altitude == expected_.altitude && |  | 
| 92            actual.accuracy == expected_.accuracy && |  | 
| 93            actual.altitude_accuracy == expected_.altitude_accuracy && |  | 
| 94            actual.heading == expected_.heading && |  | 
| 95            actual.speed == expected_.speed && |  | 
| 96            actual.timestamp == expected_.timestamp && |  | 
| 97            actual.error_code == expected_.error_code && |  | 
| 98            actual.error_message == expected_.error_message; |  | 
| 99   } |  | 
| 100 |  | 
| 101   void DescribeTo(::std::ostream* os) const override { |  | 
| 102     *os << "which matches the expected position"; |  | 
| 103   } |  | 
| 104 |  | 
| 105   void DescribeNegationTo(::std::ostream* os) const override { |  | 
| 106     *os << "which does not match the expected position"; |  | 
| 107   } |  | 
| 108 |  | 
| 109  private: |  | 
| 110   Geoposition expected_; |  | 
| 111 |  | 
| 112   DISALLOW_COPY_AND_ASSIGN(GeopositionEqMatcher); |  | 
| 113 }; |  | 
| 114 |  | 
| 115 Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) { |  | 
| 116   return MakeMatcher(new GeopositionEqMatcher(expected)); |  | 
| 117 } |  | 
| 118 |  | 
| 119 class GeolocationProviderTest : public testing::Test { |  | 
| 120  protected: |  | 
| 121   GeolocationProviderTest() |  | 
| 122       : message_loop_(), |  | 
| 123         provider_(new LocationProviderForTestArbitrator) { |  | 
| 124   } |  | 
| 125 |  | 
| 126   ~GeolocationProviderTest() override {} |  | 
| 127 |  | 
| 128   LocationProviderForTestArbitrator* provider() { return provider_.get(); } |  | 
| 129 |  | 
| 130   // Called on test thread. |  | 
| 131   bool ProvidersStarted(); |  | 
| 132   void SendMockLocation(const Geoposition& position); |  | 
| 133 |  | 
| 134  private: |  | 
| 135   // Called on provider thread. |  | 
| 136   void GetProvidersStarted(bool* started); |  | 
| 137 |  | 
| 138   base::MessageLoopForUI message_loop_; |  | 
| 139   std::unique_ptr<LocationProviderForTestArbitrator> provider_; |  | 
| 140 }; |  | 
| 141 |  | 
| 142 |  | 
| 143 bool GeolocationProviderTest::ProvidersStarted() { |  | 
| 144   DCHECK(provider_->IsRunning()); |  | 
| 145   DCHECK(base::MessageLoop::current() == &message_loop_); |  | 
| 146   bool started; |  | 
| 147   provider_->task_runner()->PostTaskAndReply( |  | 
| 148       FROM_HERE, base::Bind(&GeolocationProviderTest::GetProvidersStarted, |  | 
| 149                             base::Unretained(this), &started), |  | 
| 150       base::MessageLoop::QuitWhenIdleClosure()); |  | 
| 151   base::RunLoop().Run(); |  | 
| 152   return started; |  | 
| 153 } |  | 
| 154 |  | 
| 155 void GeolocationProviderTest::GetProvidersStarted(bool* started) { |  | 
| 156   DCHECK(provider_->task_runner()->BelongsToCurrentThread()); |  | 
| 157   *started = provider_->mock_arbitrator()->providers_started(); |  | 
| 158 } |  | 
| 159 |  | 
| 160 void GeolocationProviderTest::SendMockLocation(const Geoposition& position) { |  | 
| 161   DCHECK(provider_->IsRunning()); |  | 
| 162   DCHECK(base::MessageLoop::current() == &message_loop_); |  | 
| 163   provider_->task_runner()->PostTask( |  | 
| 164       FROM_HERE, base::Bind(&GeolocationProviderImpl::OnLocationUpdate, |  | 
| 165                             base::Unretained(provider_.get()), position)); |  | 
| 166 } |  | 
| 167 |  | 
| 168 // Regression test for http://crbug.com/59377 |  | 
| 169 TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) { |  | 
| 170   EXPECT_FALSE(provider()->user_did_opt_into_location_services_for_testing()); |  | 
| 171   provider()->UserDidOptIntoLocationServices(); |  | 
| 172   EXPECT_TRUE(provider()->user_did_opt_into_location_services_for_testing()); |  | 
| 173 } |  | 
| 174 |  | 
| 175 void DummyFunction(const Geoposition& position) { |  | 
| 176 } |  | 
| 177 |  | 
| 178 TEST_F(GeolocationProviderTest, StartStop) { |  | 
| 179   EXPECT_FALSE(provider()->IsRunning()); |  | 
| 180   GeolocationProviderImpl::LocationUpdateCallback callback = |  | 
| 181       base::Bind(&DummyFunction); |  | 
| 182   std::unique_ptr<GeolocationProvider::Subscription> subscription = |  | 
| 183       provider()->AddLocationUpdateCallback(callback, false); |  | 
| 184   EXPECT_TRUE(provider()->IsRunning()); |  | 
| 185   EXPECT_TRUE(ProvidersStarted()); |  | 
| 186 |  | 
| 187   subscription.reset(); |  | 
| 188 |  | 
| 189   EXPECT_FALSE(ProvidersStarted()); |  | 
| 190   EXPECT_TRUE(provider()->IsRunning()); |  | 
| 191 } |  | 
| 192 |  | 
| 193 TEST_F(GeolocationProviderTest, StalePositionNotSent) { |  | 
| 194   Geoposition first_position; |  | 
| 195   first_position.latitude = 12; |  | 
| 196   first_position.longitude = 34; |  | 
| 197   first_position.accuracy = 56; |  | 
| 198   first_position.timestamp = base::Time::Now(); |  | 
| 199 |  | 
| 200   AsyncMockGeolocationObserver first_observer; |  | 
| 201   GeolocationProviderImpl::LocationUpdateCallback first_callback = base::Bind( |  | 
| 202       &MockGeolocationObserver::OnLocationUpdate, |  | 
| 203       base::Unretained(&first_observer)); |  | 
| 204   EXPECT_CALL(first_observer, OnLocationUpdate(GeopositionEq(first_position))); |  | 
| 205   std::unique_ptr<GeolocationProvider::Subscription> subscription = |  | 
| 206       provider()->AddLocationUpdateCallback(first_callback, false); |  | 
| 207   SendMockLocation(first_position); |  | 
| 208   base::RunLoop().Run(); |  | 
| 209 |  | 
| 210   subscription.reset(); |  | 
| 211 |  | 
| 212   Geoposition second_position; |  | 
| 213   second_position.latitude = 13; |  | 
| 214   second_position.longitude = 34; |  | 
| 215   second_position.accuracy = 56; |  | 
| 216   second_position.timestamp = base::Time::Now(); |  | 
| 217 |  | 
| 218   AsyncMockGeolocationObserver second_observer; |  | 
| 219 |  | 
| 220   // After adding a second observer, check that no unexpected position update |  | 
| 221   // is sent. |  | 
| 222   EXPECT_CALL(second_observer, OnLocationUpdate(testing::_)).Times(0); |  | 
| 223   GeolocationProviderImpl::LocationUpdateCallback second_callback = base::Bind( |  | 
| 224       &MockGeolocationObserver::OnLocationUpdate, |  | 
| 225       base::Unretained(&second_observer)); |  | 
| 226   std::unique_ptr<GeolocationProvider::Subscription> subscription2 = |  | 
| 227       provider()->AddLocationUpdateCallback(second_callback, false); |  | 
| 228   base::RunLoop().RunUntilIdle(); |  | 
| 229 |  | 
| 230   // The second observer should receive the new position now. |  | 
| 231   EXPECT_CALL(second_observer, |  | 
| 232               OnLocationUpdate(GeopositionEq(second_position))); |  | 
| 233   SendMockLocation(second_position); |  | 
| 234   base::RunLoop().Run(); |  | 
| 235 |  | 
| 236   subscription2.reset(); |  | 
| 237   EXPECT_FALSE(ProvidersStarted()); |  | 
| 238 } |  | 
| 239 |  | 
| 240 TEST_F(GeolocationProviderTest, OverrideLocationForTesting) { |  | 
| 241   Geoposition position; |  | 
| 242   position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; |  | 
| 243   provider()->OverrideLocationForTesting(position); |  | 
| 244   // Adding an observer when the location is overridden should synchronously |  | 
| 245   // update the observer with our overridden position. |  | 
| 246   MockGeolocationObserver mock_observer; |  | 
| 247   EXPECT_CALL(mock_observer, OnLocationUpdate(GeopositionEq(position))); |  | 
| 248   GeolocationProviderImpl::LocationUpdateCallback callback = base::Bind( |  | 
| 249       &MockGeolocationObserver::OnLocationUpdate, |  | 
| 250       base::Unretained(&mock_observer)); |  | 
| 251   std::unique_ptr<GeolocationProvider::Subscription> subscription = |  | 
| 252       provider()->AddLocationUpdateCallback(callback, false); |  | 
| 253   subscription.reset(); |  | 
| 254   // Wait for the providers to be stopped now that all clients are gone. |  | 
| 255   EXPECT_FALSE(ProvidersStarted()); |  | 
| 256 } |  | 
| 257 |  | 
| 258 }  // namespace device |  | 
| OLD | NEW | 
|---|