blob: 0ae4c1c0d472d982f8b12e5951bdec1d6ecf3044 [file] [log] [blame]
[email protected]a980b052012-04-20 12:42:491// Copyright (c) 2012 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"
[email protected]439eb402012-05-04 13:04:447#include "base/memory/ref_counted.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/message_loop.h"
[email protected]f40000c62012-05-11 15:57:0710#include "base/string16.h"
[email protected]439eb402012-05-04 13:04:4411#include "base/time.h"
[email protected]6d444ddf2013-05-07 17:10:4412#include "content/browser/geolocation/geolocation_provider_impl.h"
[email protected]f40000c62012-05-11 15:57:0713#include "content/browser/geolocation/location_provider.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]f40000c62012-05-11 15:57:0718#include "googleurl/src/gurl.h"
[email protected]60349d92011-09-06 11:00:4119#include "testing/gmock/include/gmock/gmock.h"
[email protected]fa7e91b82010-10-20 09:29:2720#include "testing/gtest/include/gtest/gtest.h"
21
[email protected]439eb402012-05-04 13:04:4422using testing::MakeMatcher;
23using testing::Matcher;
24using testing::MatcherInterface;
25using testing::MatchResultListener;
[email protected]60349d92011-09-06 11:00:4126
[email protected]6bd40832012-10-29 03:01:4927namespace content {
[email protected]439eb402012-05-04 13:04:4428
[email protected]6d444ddf2013-05-07 17:10:4429class LocationProviderForTestArbitrator : public GeolocationProviderImpl {
[email protected]b7c5c262012-11-26 13:17:1830 public:
[email protected]90984b02012-11-30 13:00:4031 LocationProviderForTestArbitrator() : mock_arbitrator_(NULL) {}
[email protected]b7c5c262012-11-26 13:17:1832 virtual ~LocationProviderForTestArbitrator() {}
33
[email protected]90984b02012-11-30 13:00:4034 // Only valid for use on the geolocation thread.
35 MockGeolocationArbitrator* mock_arbitrator() const {
36 return mock_arbitrator_;
37 }
38
[email protected]b7c5c262012-11-26 13:17:1839 protected:
[email protected]6d444ddf2013-05-07 17:10:4440 // GeolocationProviderImpl implementation:
[email protected]b7c5c262012-11-26 13:17:1841 virtual GeolocationArbitrator* CreateArbitrator() OVERRIDE;
42
43 private:
[email protected]90984b02012-11-30 13:00:4044 MockGeolocationArbitrator* mock_arbitrator_;
[email protected]439eb402012-05-04 13:04:4445};
46
[email protected]b7c5c262012-11-26 13:17:1847GeolocationArbitrator* LocationProviderForTestArbitrator::CreateArbitrator() {
[email protected]90984b02012-11-30 13:00:4048 DCHECK(mock_arbitrator_ == NULL);
49 mock_arbitrator_ = new MockGeolocationArbitrator;
50 return mock_arbitrator_;
[email protected]b7c5c262012-11-26 13:17:1851}
52
[email protected]6d444ddf2013-05-07 17:10:4453class GeolocationObserver {
[email protected]439eb402012-05-04 13:04:4454 public:
[email protected]6d444ddf2013-05-07 17:10:4455 virtual ~GeolocationObserver() {}
56 virtual void OnLocationUpdate(const Geoposition& position) = 0;
[email protected]439eb402012-05-04 13:04:4457};
58
59class MockGeolocationObserver : public GeolocationObserver {
60 public:
[email protected]6bd40832012-10-29 03:01:4961 MOCK_METHOD1(OnLocationUpdate, void(const Geoposition& position));
[email protected]439eb402012-05-04 13:04:4462};
63
[email protected]baaf1842012-12-03 20:54:5464class AsyncMockGeolocationObserver : public MockGeolocationObserver {
65 public:
[email protected]c3e35892013-02-12 02:08:0166 virtual void OnLocationUpdate(const Geoposition& position) OVERRIDE {
[email protected]baaf1842012-12-03 20:54:5467 MockGeolocationObserver::OnLocationUpdate(position);
[email protected]dd32b1272013-05-04 14:17:1168 base::MessageLoop::current()->Quit();
[email protected]baaf1842012-12-03 20:54:5469 }
70};
71
[email protected]439eb402012-05-04 13:04:4472class MockGeolocationCallbackWrapper {
73 public:
[email protected]6bd40832012-10-29 03:01:4974 MOCK_METHOD1(Callback, void(const Geoposition& position));
[email protected]439eb402012-05-04 13:04:4475};
76
77class GeopositionEqMatcher
[email protected]6bd40832012-10-29 03:01:4978 : public MatcherInterface<const Geoposition&> {
[email protected]439eb402012-05-04 13:04:4479 public:
[email protected]6bd40832012-10-29 03:01:4980 explicit GeopositionEqMatcher(const Geoposition& expected)
[email protected]439eb402012-05-04 13:04:4481 : expected_(expected) {}
82
[email protected]6bd40832012-10-29 03:01:4983 virtual bool MatchAndExplain(const Geoposition& actual,
[email protected]439eb402012-05-04 13:04:4484 MatchResultListener* listener) const OVERRIDE {
85 return actual.latitude == expected_.latitude &&
86 actual.longitude == expected_.longitude &&
87 actual.altitude == expected_.altitude &&
88 actual.accuracy == expected_.accuracy &&
89 actual.altitude_accuracy == expected_.altitude_accuracy &&
90 actual.heading == expected_.heading &&
91 actual.speed == expected_.speed &&
92 actual.timestamp == expected_.timestamp &&
93 actual.error_code == expected_.error_code &&
94 actual.error_message == expected_.error_message;
95 }
96
97 virtual void DescribeTo(::std::ostream* os) const OVERRIDE {
98 *os << "which matches the expected position";
99 }
100
101 virtual void DescribeNegationTo(::std::ostream* os) const OVERRIDE{
102 *os << "which does not match the expected position";
103 }
104
105 private:
[email protected]6bd40832012-10-29 03:01:49106 Geoposition expected_;
[email protected]439eb402012-05-04 13:04:44107
108 DISALLOW_COPY_AND_ASSIGN(GeopositionEqMatcher);
109};
110
[email protected]6bd40832012-10-29 03:01:49111Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) {
[email protected]439eb402012-05-04 13:04:44112 return MakeMatcher(new GeopositionEqMatcher(expected));
113}
[email protected]fa7e91b82010-10-20 09:29:27114
115class GeolocationProviderTest : public testing::Test {
116 protected:
[email protected]fa7e91b82010-10-20 09:29:27117 GeolocationProviderTest()
[email protected]439eb402012-05-04 13:04:44118 : message_loop_(),
[email protected]6bd40832012-10-29 03:01:49119 io_thread_(BrowserThread::IO, &message_loop_),
[email protected]90984b02012-11-30 13:00:40120 provider_(new LocationProviderForTestArbitrator) {
[email protected]b7d6acc2011-02-03 11:01:50121 }
122
[email protected]c3e35892013-02-12 02:08:01123 virtual ~GeolocationProviderTest() {}
[email protected]b7d6acc2011-02-03 11:01:50124
[email protected]90984b02012-11-30 13:00:40125 LocationProviderForTestArbitrator* provider() { return provider_.get(); }
126
127 // Called on test thread.
128 bool ProvidersStarted();
[email protected]baaf1842012-12-03 20:54:54129 void SendMockLocation(const Geoposition& position);
[email protected]90984b02012-11-30 13:00:40130
131 private:
132 // Called on provider thread.
133 void GetProvidersStarted(bool* started);
[email protected]d4cee672012-05-09 17:36:07134
[email protected]dd32b1272013-05-04 14:17:11135 base::MessageLoop message_loop_;
[email protected]6bd40832012-10-29 03:01:49136 TestBrowserThread io_thread_;
[email protected]b7c5c262012-11-26 13:17:18137 scoped_ptr<LocationProviderForTestArbitrator> provider_;
[email protected]fa7e91b82010-10-20 09:29:27138};
139
[email protected]90984b02012-11-30 13:00:40140
141bool GeolocationProviderTest::ProvidersStarted() {
142 DCHECK(provider_->IsRunning());
[email protected]dd32b1272013-05-04 14:17:11143 DCHECK(base::MessageLoop::current() == &message_loop_);
[email protected]90984b02012-11-30 13:00:40144 bool started;
145 provider_->message_loop_proxy()->PostTaskAndReply(
146 FROM_HERE,
147 base::Bind(&GeolocationProviderTest::GetProvidersStarted,
148 base::Unretained(this),
149 &started),
[email protected]dd32b1272013-05-04 14:17:11150 base::MessageLoop::QuitClosure());
[email protected]90984b02012-11-30 13:00:40151 message_loop_.Run();
152 return started;
153}
154
155void GeolocationProviderTest::GetProvidersStarted(bool* started) {
[email protected]dd32b1272013-05-04 14:17:11156 DCHECK(base::MessageLoop::current() == provider_->message_loop());
[email protected]90984b02012-11-30 13:00:40157 *started = provider_->mock_arbitrator()->providers_started();
158}
159
[email protected]baaf1842012-12-03 20:54:54160void GeolocationProviderTest::SendMockLocation(const Geoposition& position) {
161 DCHECK(provider_->IsRunning());
[email protected]dd32b1272013-05-04 14:17:11162 DCHECK(base::MessageLoop::current() == &message_loop_);
163 provider_->message_loop()
164 ->PostTask(FROM_HERE,
[email protected]6d444ddf2013-05-07 17:10:44165 base::Bind(&GeolocationProviderImpl::OnLocationUpdate,
[email protected]dd32b1272013-05-04 14:17:11166 base::Unretained(provider_.get()),
167 position));
[email protected]baaf1842012-12-03 20:54:54168}
[email protected]90984b02012-11-30 13:00:40169
[email protected]fa7e91b82010-10-20 09:29:27170// Regression test for http://crbug.com/59377
171TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) {
[email protected]6d444ddf2013-05-07 17:10:44172 EXPECT_FALSE(provider()->LocationServicesOptedIn());
173 provider()->UserDidOptIntoLocationServices();
174 EXPECT_TRUE(provider()->LocationServicesOptedIn());
[email protected]fa7e91b82010-10-20 09:29:27175}
176
[email protected]b7d6acc2011-02-03 11:01:50177TEST_F(GeolocationProviderTest, StartStop) {
[email protected]90984b02012-11-30 13:00:40178 EXPECT_FALSE(provider()->IsRunning());
[email protected]6d444ddf2013-05-07 17:10:44179 GeolocationProviderImpl::LocationUpdateCallback null_callback;
180 provider()->AddLocationUpdateCallback(null_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]6d444ddf2013-05-07 17:10:44184 provider()->RemoveLocationUpdateCallback(null_callback);
[email protected]90984b02012-11-30 13:00:40185 EXPECT_FALSE(ProvidersStarted());
186 EXPECT_TRUE(provider()->IsRunning());
[email protected]b7d6acc2011-02-03 11:01:50187}
188
[email protected]baaf1842012-12-03 20:54:54189TEST_F(GeolocationProviderTest, StalePositionNotSent) {
190 Geoposition first_position;
191 first_position.latitude = 12;
192 first_position.longitude = 34;
193 first_position.accuracy = 56;
194 first_position.timestamp = base::Time::Now();
195
196 AsyncMockGeolocationObserver first_observer;
[email protected]6d444ddf2013-05-07 17:10:44197 GeolocationProviderImpl::LocationUpdateCallback first_callback = base::Bind(
198 &MockGeolocationObserver::OnLocationUpdate,
199 base::Unretained(&first_observer));
[email protected]baaf1842012-12-03 20:54:54200 EXPECT_CALL(first_observer, OnLocationUpdate(GeopositionEq(first_position)));
[email protected]6d444ddf2013-05-07 17:10:44201 provider()->AddLocationUpdateCallback(first_callback, false);
[email protected]baaf1842012-12-03 20:54:54202 SendMockLocation(first_position);
[email protected]dd32b1272013-05-04 14:17:11203 base::MessageLoop::current()->Run();
[email protected]baaf1842012-12-03 20:54:54204
[email protected]6d444ddf2013-05-07 17:10:44205 provider()->RemoveLocationUpdateCallback(first_callback);
[email protected]baaf1842012-12-03 20:54:54206
207 Geoposition second_position;
208 second_position.latitude = 13;
209 second_position.longitude = 34;
210 second_position.accuracy = 56;
211 second_position.timestamp = base::Time::Now();
212
213 AsyncMockGeolocationObserver second_observer;
214
215 // After adding a second observer, check that no unexpected position update
216 // is sent.
217 EXPECT_CALL(second_observer, OnLocationUpdate(testing::_)).Times(0);
[email protected]6d444ddf2013-05-07 17:10:44218 GeolocationProviderImpl::LocationUpdateCallback second_callback = base::Bind(
219 &MockGeolocationObserver::OnLocationUpdate,
220 base::Unretained(&second_observer));
221 provider()->AddLocationUpdateCallback(second_callback, false);
[email protected]dd32b1272013-05-04 14:17:11222 base::MessageLoop::current()->RunUntilIdle();
[email protected]baaf1842012-12-03 20:54:54223
224 // The second observer should receive the new position now.
225 EXPECT_CALL(second_observer,
226 OnLocationUpdate(GeopositionEq(second_position)));
227 SendMockLocation(second_position);
[email protected]dd32b1272013-05-04 14:17:11228 base::MessageLoop::current()->Run();
[email protected]baaf1842012-12-03 20:54:54229
[email protected]6d444ddf2013-05-07 17:10:44230 provider()->RemoveLocationUpdateCallback(second_callback);
[email protected]baaf1842012-12-03 20:54:54231 EXPECT_FALSE(ProvidersStarted());
232}
233
[email protected]f40000c62012-05-11 15:57:07234TEST_F(GeolocationProviderTest, OverrideLocationForTesting) {
[email protected]6bd40832012-10-29 03:01:49235 Geoposition position;
236 position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
[email protected]90984b02012-11-30 13:00:40237 provider()->OverrideLocationForTesting(position);
[email protected]439eb402012-05-04 13:04:44238 // Adding an observer when the location is overridden should synchronously
239 // update the observer with our overridden position.
[email protected]02a5fe292012-04-25 21:47:56240 MockGeolocationObserver mock_observer;
[email protected]439eb402012-05-04 13:04:44241 EXPECT_CALL(mock_observer, OnLocationUpdate(GeopositionEq(position)));
[email protected]6d444ddf2013-05-07 17:10:44242 GeolocationProviderImpl::LocationUpdateCallback callback = base::Bind(
243 &MockGeolocationObserver::OnLocationUpdate,
244 base::Unretained(&mock_observer));
245 provider()->AddLocationUpdateCallback(callback, false);
246 provider()->RemoveLocationUpdateCallback(callback);
[email protected]d4cee672012-05-09 17:36:07247 // Wait for the providers to be stopped now that all clients are gone.
[email protected]90984b02012-11-30 13:00:40248 EXPECT_FALSE(ProvidersStarted());
[email protected]02a5fe292012-04-25 21:47:56249}
250
[email protected]6bd40832012-10-29 03:01:49251} // namespace content