blob: 491856bfa9982c8c4eea61150ee2042b1bc2a725 [file] [log] [blame]
[email protected]6ca7dc12014-08-15 09:43:321// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]fa7e91b82010-10-20 09:29:272// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]439eb402012-05-04 13:04:445#include "base/bind.h"
6#include "base/bind_helpers.h"
skyostil95082a62015-06-05 19:53:077#include "base/location.h"
[email protected]439eb402012-05-04 13:04:448#include "base/memory/ref_counted.h"
9#include "base/memory/scoped_ptr.h"
skyostil95082a62015-06-05 19:53:0710#include "base/single_thread_task_runner.h"
[email protected]10994d132013-06-11 07:16:1811#include "base/strings/string16.h"
[email protected]a43858f2013-06-28 15:18:3712#include "base/time/time.h"
[email protected]6d444ddf2013-05-07 17:10:4413#include "content/browser/geolocation/geolocation_provider_impl.h"
[email protected]90984b02012-11-30 13:00:4014#include "content/browser/geolocation/mock_location_arbitrator.h"
[email protected]f40000c62012-05-11 15:57:0715#include "content/public/browser/access_token_store.h"
[email protected]439eb402012-05-04 13:04:4416#include "content/public/browser/browser_thread.h"
[email protected]e97882f2012-06-04 02:23:1717#include "content/public/test/test_browser_thread.h"
[email protected]60349d92011-09-06 11:00:4118#include "testing/gmock/include/gmock/gmock.h"
[email protected]fa7e91b82010-10-20 09:29:2719#include "testing/gtest/include/gtest/gtest.h"
20
[email protected]439eb402012-05-04 13:04:4421using testing::MakeMatcher;
22using testing::Matcher;
23using testing::MatcherInterface;
24using testing::MatchResultListener;
[email protected]60349d92011-09-06 11:00:4125
[email protected]6bd40832012-10-29 03:01:4926namespace content {
[email protected]439eb402012-05-04 13:04:4427
[email protected]6d444ddf2013-05-07 17:10:4428class LocationProviderForTestArbitrator : public GeolocationProviderImpl {
[email protected]b7c5c262012-11-26 13:17:1829 public:
[email protected]90984b02012-11-30 13:00:4030 LocationProviderForTestArbitrator() : mock_arbitrator_(NULL) {}
dchengc2282aa2014-10-21 12:07:5831 ~LocationProviderForTestArbitrator() override {}
[email protected]b7c5c262012-11-26 13:17:1832
[email protected]90984b02012-11-30 13:00:4033 // Only valid for use on the geolocation thread.
[email protected]73d8e1d82013-09-10 20:52:0934 MockLocationArbitrator* mock_arbitrator() const {
[email protected]90984b02012-11-30 13:00:4035 return mock_arbitrator_;
36 }
37
[email protected]b7c5c262012-11-26 13:17:1838 protected:
[email protected]6d444ddf2013-05-07 17:10:4439 // GeolocationProviderImpl implementation:
dchengc2282aa2014-10-21 12:07:5840 LocationArbitrator* CreateArbitrator() override;
[email protected]b7c5c262012-11-26 13:17:1841
42 private:
[email protected]73d8e1d82013-09-10 20:52:0943 MockLocationArbitrator* mock_arbitrator_;
[email protected]439eb402012-05-04 13:04:4444};
45
[email protected]73d8e1d82013-09-10 20:52:0946LocationArbitrator* LocationProviderForTestArbitrator::CreateArbitrator() {
[email protected]90984b02012-11-30 13:00:4047 DCHECK(mock_arbitrator_ == NULL);
[email protected]73d8e1d82013-09-10 20:52:0948 mock_arbitrator_ = new MockLocationArbitrator;
[email protected]90984b02012-11-30 13:00:4049 return mock_arbitrator_;
[email protected]b7c5c262012-11-26 13:17:1850}
51
[email protected]6d444ddf2013-05-07 17:10:4452class GeolocationObserver {
[email protected]439eb402012-05-04 13:04:4453 public:
[email protected]6d444ddf2013-05-07 17:10:4454 virtual ~GeolocationObserver() {}
55 virtual void OnLocationUpdate(const Geoposition& position) = 0;
[email protected]439eb402012-05-04 13:04:4456};
57
58class MockGeolocationObserver : public GeolocationObserver {
59 public:
[email protected]6bd40832012-10-29 03:01:4960 MOCK_METHOD1(OnLocationUpdate, void(const Geoposition& position));
[email protected]439eb402012-05-04 13:04:4461};
62
[email protected]baaf1842012-12-03 20:54:5463class AsyncMockGeolocationObserver : public MockGeolocationObserver {
64 public:
dchengc2282aa2014-10-21 12:07:5865 void OnLocationUpdate(const Geoposition& position) override {
[email protected]baaf1842012-12-03 20:54:5466 MockGeolocationObserver::OnLocationUpdate(position);
ki.stfu800779242015-10-12 22:46:2667 base::MessageLoop::current()->QuitWhenIdle();
[email protected]baaf1842012-12-03 20:54:5468 }
69};
70
[email protected]439eb402012-05-04 13:04:4471class MockGeolocationCallbackWrapper {
72 public:
[email protected]6bd40832012-10-29 03:01:4973 MOCK_METHOD1(Callback, void(const Geoposition& position));
[email protected]439eb402012-05-04 13:04:4474};
75
76class GeopositionEqMatcher
[email protected]6bd40832012-10-29 03:01:4977 : public MatcherInterface<const Geoposition&> {
[email protected]439eb402012-05-04 13:04:4478 public:
[email protected]6bd40832012-10-29 03:01:4979 explicit GeopositionEqMatcher(const Geoposition& expected)
[email protected]439eb402012-05-04 13:04:4480 : expected_(expected) {}
81
nick51208922015-04-24 21:38:3782 bool MatchAndExplain(const Geoposition& actual,
83 MatchResultListener* listener) const override {
[email protected]439eb402012-05-04 13:04:4484 return actual.latitude == expected_.latitude &&
85 actual.longitude == expected_.longitude &&
86 actual.altitude == expected_.altitude &&
87 actual.accuracy == expected_.accuracy &&
88 actual.altitude_accuracy == expected_.altitude_accuracy &&
89 actual.heading == expected_.heading &&
90 actual.speed == expected_.speed &&
91 actual.timestamp == expected_.timestamp &&
92 actual.error_code == expected_.error_code &&
93 actual.error_message == expected_.error_message;
94 }
95
nick51208922015-04-24 21:38:3796 void DescribeTo(::std::ostream* os) const override {
[email protected]439eb402012-05-04 13:04:4497 *os << "which matches the expected position";
98 }
99
nick51208922015-04-24 21:38:37100 void DescribeNegationTo(::std::ostream* os) const override {
[email protected]439eb402012-05-04 13:04:44101 *os << "which does not match the expected position";
102 }
103
104 private:
[email protected]6bd40832012-10-29 03:01:49105 Geoposition expected_;
[email protected]439eb402012-05-04 13:04:44106
107 DISALLOW_COPY_AND_ASSIGN(GeopositionEqMatcher);
108};
109
[email protected]6bd40832012-10-29 03:01:49110Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) {
[email protected]439eb402012-05-04 13:04:44111 return MakeMatcher(new GeopositionEqMatcher(expected));
112}
[email protected]fa7e91b82010-10-20 09:29:27113
114class GeolocationProviderTest : public testing::Test {
115 protected:
[email protected]fa7e91b82010-10-20 09:29:27116 GeolocationProviderTest()
[email protected]439eb402012-05-04 13:04:44117 : message_loop_(),
[email protected]f28ef9a32014-05-12 16:36:10118 ui_thread_(BrowserThread::UI, &message_loop_),
[email protected]90984b02012-11-30 13:00:40119 provider_(new LocationProviderForTestArbitrator) {
[email protected]b7d6acc2011-02-03 11:01:50120 }
121
dchengfa85b152014-10-28 01:13:42122 ~GeolocationProviderTest() override {}
[email protected]b7d6acc2011-02-03 11:01:50123
[email protected]90984b02012-11-30 13:00:40124 LocationProviderForTestArbitrator* provider() { return provider_.get(); }
125
126 // Called on test thread.
127 bool ProvidersStarted();
[email protected]baaf1842012-12-03 20:54:54128 void SendMockLocation(const Geoposition& position);
[email protected]90984b02012-11-30 13:00:40129
130 private:
131 // Called on provider thread.
132 void GetProvidersStarted(bool* started);
[email protected]d4cee672012-05-09 17:36:07133
[email protected]dd32b1272013-05-04 14:17:11134 base::MessageLoop message_loop_;
[email protected]f28ef9a32014-05-12 16:36:10135 TestBrowserThread ui_thread_;
[email protected]b7c5c262012-11-26 13:17:18136 scoped_ptr<LocationProviderForTestArbitrator> provider_;
[email protected]fa7e91b82010-10-20 09:29:27137};
138
[email protected]90984b02012-11-30 13:00:40139
140bool GeolocationProviderTest::ProvidersStarted() {
141 DCHECK(provider_->IsRunning());
[email protected]dd32b1272013-05-04 14:17:11142 DCHECK(base::MessageLoop::current() == &message_loop_);
[email protected]90984b02012-11-30 13:00:40143 bool started;
skyostil95082a62015-06-05 19:53:07144 provider_->task_runner()->PostTaskAndReply(
145 FROM_HERE, base::Bind(&GeolocationProviderTest::GetProvidersStarted,
146 base::Unretained(this), &started),
ki.stfu800779242015-10-12 22:46:26147 base::MessageLoop::QuitWhenIdleClosure());
[email protected]90984b02012-11-30 13:00:40148 message_loop_.Run();
149 return started;
150}
151
152void GeolocationProviderTest::GetProvidersStarted(bool* started) {
[email protected]dd32b1272013-05-04 14:17:11153 DCHECK(base::MessageLoop::current() == provider_->message_loop());
[email protected]90984b02012-11-30 13:00:40154 *started = provider_->mock_arbitrator()->providers_started();
155}
156
[email protected]baaf1842012-12-03 20:54:54157void GeolocationProviderTest::SendMockLocation(const Geoposition& position) {
158 DCHECK(provider_->IsRunning());
[email protected]dd32b1272013-05-04 14:17:11159 DCHECK(base::MessageLoop::current() == &message_loop_);
skyostil95082a62015-06-05 19:53:07160 provider_->task_runner()->PostTask(
161 FROM_HERE, base::Bind(&GeolocationProviderImpl::OnLocationUpdate,
162 base::Unretained(provider_.get()), position));
[email protected]baaf1842012-12-03 20:54:54163}
[email protected]90984b02012-11-30 13:00:40164
[email protected]fa7e91b82010-10-20 09:29:27165// Regression test for http://crbug.com/59377
166TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) {
[email protected]f28ef9a32014-05-12 16:36:10167 EXPECT_FALSE(provider()->user_did_opt_into_location_services_for_testing());
[email protected]6d444ddf2013-05-07 17:10:44168 provider()->UserDidOptIntoLocationServices();
[email protected]f28ef9a32014-05-12 16:36:10169 EXPECT_TRUE(provider()->user_did_opt_into_location_services_for_testing());
170}
171
172void DummyFunction(const Geoposition& position) {
[email protected]fa7e91b82010-10-20 09:29:27173}
174
[email protected]b7d6acc2011-02-03 11:01:50175TEST_F(GeolocationProviderTest, StartStop) {
[email protected]90984b02012-11-30 13:00:40176 EXPECT_FALSE(provider()->IsRunning());
[email protected]f28ef9a32014-05-12 16:36:10177 GeolocationProviderImpl::LocationUpdateCallback callback =
178 base::Bind(&DummyFunction);
179 scoped_ptr<content::GeolocationProvider::Subscription> subscription =
180 provider()->AddLocationUpdateCallback(callback, false);
[email protected]90984b02012-11-30 13:00:40181 EXPECT_TRUE(provider()->IsRunning());
182 EXPECT_TRUE(ProvidersStarted());
[email protected]439eb402012-05-04 13:04:44183
[email protected]f28ef9a32014-05-12 16:36:10184 subscription.reset();
185
[email protected]90984b02012-11-30 13:00:40186 EXPECT_FALSE(ProvidersStarted());
187 EXPECT_TRUE(provider()->IsRunning());
[email protected]b7d6acc2011-02-03 11:01:50188}
189
[email protected]baaf1842012-12-03 20:54:54190TEST_F(GeolocationProviderTest, StalePositionNotSent) {
191 Geoposition first_position;
192 first_position.latitude = 12;
193 first_position.longitude = 34;
194 first_position.accuracy = 56;
195 first_position.timestamp = base::Time::Now();
196
197 AsyncMockGeolocationObserver first_observer;
[email protected]6d444ddf2013-05-07 17:10:44198 GeolocationProviderImpl::LocationUpdateCallback first_callback = base::Bind(
199 &MockGeolocationObserver::OnLocationUpdate,
200 base::Unretained(&first_observer));
[email protected]baaf1842012-12-03 20:54:54201 EXPECT_CALL(first_observer, OnLocationUpdate(GeopositionEq(first_position)));
[email protected]f28ef9a32014-05-12 16:36:10202 scoped_ptr<content::GeolocationProvider::Subscription> subscription =
203 provider()->AddLocationUpdateCallback(first_callback, false);
[email protected]baaf1842012-12-03 20:54:54204 SendMockLocation(first_position);
[email protected]dd32b1272013-05-04 14:17:11205 base::MessageLoop::current()->Run();
[email protected]baaf1842012-12-03 20:54:54206
[email protected]f28ef9a32014-05-12 16:36:10207 subscription.reset();
[email protected]baaf1842012-12-03 20:54:54208
209 Geoposition second_position;
210 second_position.latitude = 13;
211 second_position.longitude = 34;
212 second_position.accuracy = 56;
213 second_position.timestamp = base::Time::Now();
214
215 AsyncMockGeolocationObserver second_observer;
216
217 // After adding a second observer, check that no unexpected position update
218 // is sent.
219 EXPECT_CALL(second_observer, OnLocationUpdate(testing::_)).Times(0);
[email protected]6d444ddf2013-05-07 17:10:44220 GeolocationProviderImpl::LocationUpdateCallback second_callback = base::Bind(
221 &MockGeolocationObserver::OnLocationUpdate,
222 base::Unretained(&second_observer));
[email protected]f28ef9a32014-05-12 16:36:10223 scoped_ptr<content::GeolocationProvider::Subscription> subscription2 =
224 provider()->AddLocationUpdateCallback(second_callback, false);
[email protected]dd32b1272013-05-04 14:17:11225 base::MessageLoop::current()->RunUntilIdle();
[email protected]baaf1842012-12-03 20:54:54226
227 // The second observer should receive the new position now.
228 EXPECT_CALL(second_observer,
229 OnLocationUpdate(GeopositionEq(second_position)));
230 SendMockLocation(second_position);
[email protected]dd32b1272013-05-04 14:17:11231 base::MessageLoop::current()->Run();
[email protected]baaf1842012-12-03 20:54:54232
[email protected]f28ef9a32014-05-12 16:36:10233 subscription2.reset();
[email protected]baaf1842012-12-03 20:54:54234 EXPECT_FALSE(ProvidersStarted());
235}
236
[email protected]f40000c62012-05-11 15:57:07237TEST_F(GeolocationProviderTest, OverrideLocationForTesting) {
[email protected]6bd40832012-10-29 03:01:49238 Geoposition position;
239 position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
[email protected]90984b02012-11-30 13:00:40240 provider()->OverrideLocationForTesting(position);
[email protected]439eb402012-05-04 13:04:44241 // Adding an observer when the location is overridden should synchronously
242 // update the observer with our overridden position.
[email protected]02a5fe292012-04-25 21:47:56243 MockGeolocationObserver mock_observer;
[email protected]439eb402012-05-04 13:04:44244 EXPECT_CALL(mock_observer, OnLocationUpdate(GeopositionEq(position)));
[email protected]6d444ddf2013-05-07 17:10:44245 GeolocationProviderImpl::LocationUpdateCallback callback = base::Bind(
246 &MockGeolocationObserver::OnLocationUpdate,
247 base::Unretained(&mock_observer));
[email protected]f28ef9a32014-05-12 16:36:10248 scoped_ptr<content::GeolocationProvider::Subscription> subscription =
249 provider()->AddLocationUpdateCallback(callback, false);
250 subscription.reset();
[email protected]d4cee672012-05-09 17:36:07251 // Wait for the providers to be stopped now that all clients are gone.
[email protected]90984b02012-11-30 13:00:40252 EXPECT_FALSE(ProvidersStarted());
[email protected]02a5fe292012-04-25 21:47:56253}
254
[email protected]6bd40832012-10-29 03:01:49255} // namespace content