blob: ea2270091f4224d964543405ea1799ab33ea5a92 [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]87678d992011-02-28 17:33:3012#include "content/browser/geolocation/geolocation_provider.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]b7c5c262012-11-26 13:17:1829class LocationProviderForTestArbitrator : public GeolocationProvider {
30 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:
40 // GeolocationProvider implementation:
41 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]439eb402012-05-04 13:04:4453class NullGeolocationObserver : public GeolocationObserver {
54 public:
55 // GeolocationObserver
[email protected]c3e35892013-02-12 02:08:0156 virtual void OnLocationUpdate(const Geoposition& position) OVERRIDE {}
[email protected]439eb402012-05-04 13:04:4457};
58
59class MockGeolocationObserver : public GeolocationObserver {
60 public:
61 // GeolocationObserver
[email protected]6bd40832012-10-29 03:01:4962 MOCK_METHOD1(OnLocationUpdate, void(const Geoposition& position));
[email protected]439eb402012-05-04 13:04:4463};
64
[email protected]baaf1842012-12-03 20:54:5465class AsyncMockGeolocationObserver : public MockGeolocationObserver {
66 public:
67 // GeolocationObserver
[email protected]c3e35892013-02-12 02:08:0168 virtual void OnLocationUpdate(const Geoposition& position) OVERRIDE {
[email protected]baaf1842012-12-03 20:54:5469 MockGeolocationObserver::OnLocationUpdate(position);
[email protected]dd32b1272013-05-04 14:17:1170 base::MessageLoop::current()->Quit();
[email protected]baaf1842012-12-03 20:54:5471 }
72};
73
[email protected]439eb402012-05-04 13:04:4474class MockGeolocationCallbackWrapper {
75 public:
[email protected]6bd40832012-10-29 03:01:4976 MOCK_METHOD1(Callback, void(const Geoposition& position));
[email protected]439eb402012-05-04 13:04:4477};
78
79class GeopositionEqMatcher
[email protected]6bd40832012-10-29 03:01:4980 : public MatcherInterface<const Geoposition&> {
[email protected]439eb402012-05-04 13:04:4481 public:
[email protected]6bd40832012-10-29 03:01:4982 explicit GeopositionEqMatcher(const Geoposition& expected)
[email protected]439eb402012-05-04 13:04:4483 : expected_(expected) {}
84
[email protected]6bd40832012-10-29 03:01:4985 virtual bool MatchAndExplain(const Geoposition& actual,
[email protected]439eb402012-05-04 13:04:4486 MatchResultListener* listener) const OVERRIDE {
87 return actual.latitude == expected_.latitude &&
88 actual.longitude == expected_.longitude &&
89 actual.altitude == expected_.altitude &&
90 actual.accuracy == expected_.accuracy &&
91 actual.altitude_accuracy == expected_.altitude_accuracy &&
92 actual.heading == expected_.heading &&
93 actual.speed == expected_.speed &&
94 actual.timestamp == expected_.timestamp &&
95 actual.error_code == expected_.error_code &&
96 actual.error_message == expected_.error_message;
97 }
98
99 virtual void DescribeTo(::std::ostream* os) const OVERRIDE {
100 *os << "which matches the expected position";
101 }
102
103 virtual void DescribeNegationTo(::std::ostream* os) const OVERRIDE{
104 *os << "which does not match the expected position";
105 }
106
107 private:
[email protected]6bd40832012-10-29 03:01:49108 Geoposition expected_;
[email protected]439eb402012-05-04 13:04:44109
110 DISALLOW_COPY_AND_ASSIGN(GeopositionEqMatcher);
111};
112
[email protected]6bd40832012-10-29 03:01:49113Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) {
[email protected]439eb402012-05-04 13:04:44114 return MakeMatcher(new GeopositionEqMatcher(expected));
115}
[email protected]fa7e91b82010-10-20 09:29:27116
117class GeolocationProviderTest : public testing::Test {
118 protected:
[email protected]fa7e91b82010-10-20 09:29:27119 GeolocationProviderTest()
[email protected]439eb402012-05-04 13:04:44120 : message_loop_(),
[email protected]6bd40832012-10-29 03:01:49121 io_thread_(BrowserThread::IO, &message_loop_),
[email protected]90984b02012-11-30 13:00:40122 provider_(new LocationProviderForTestArbitrator) {
[email protected]b7d6acc2011-02-03 11:01:50123 }
124
[email protected]c3e35892013-02-12 02:08:01125 virtual ~GeolocationProviderTest() {}
[email protected]b7d6acc2011-02-03 11:01:50126
[email protected]90984b02012-11-30 13:00:40127 LocationProviderForTestArbitrator* provider() { return provider_.get(); }
128
129 // Called on test thread.
130 bool ProvidersStarted();
[email protected]baaf1842012-12-03 20:54:54131 void SendMockLocation(const Geoposition& position);
[email protected]90984b02012-11-30 13:00:40132
133 private:
134 // Called on provider thread.
135 void GetProvidersStarted(bool* started);
[email protected]d4cee672012-05-09 17:36:07136
[email protected]dd32b1272013-05-04 14:17:11137 base::MessageLoop message_loop_;
[email protected]6bd40832012-10-29 03:01:49138 TestBrowserThread io_thread_;
[email protected]b7c5c262012-11-26 13:17:18139 scoped_ptr<LocationProviderForTestArbitrator> provider_;
[email protected]fa7e91b82010-10-20 09:29:27140};
141
[email protected]90984b02012-11-30 13:00:40142
143bool GeolocationProviderTest::ProvidersStarted() {
144 DCHECK(provider_->IsRunning());
[email protected]dd32b1272013-05-04 14:17:11145 DCHECK(base::MessageLoop::current() == &message_loop_);
[email protected]90984b02012-11-30 13:00:40146 bool started;
147 provider_->message_loop_proxy()->PostTaskAndReply(
148 FROM_HERE,
149 base::Bind(&GeolocationProviderTest::GetProvidersStarted,
150 base::Unretained(this),
151 &started),
[email protected]dd32b1272013-05-04 14:17:11152 base::MessageLoop::QuitClosure());
[email protected]90984b02012-11-30 13:00:40153 message_loop_.Run();
154 return started;
155}
156
157void GeolocationProviderTest::GetProvidersStarted(bool* started) {
[email protected]dd32b1272013-05-04 14:17:11158 DCHECK(base::MessageLoop::current() == provider_->message_loop());
[email protected]90984b02012-11-30 13:00:40159 *started = provider_->mock_arbitrator()->providers_started();
160}
161
[email protected]baaf1842012-12-03 20:54:54162void GeolocationProviderTest::SendMockLocation(const Geoposition& position) {
163 DCHECK(provider_->IsRunning());
[email protected]dd32b1272013-05-04 14:17:11164 DCHECK(base::MessageLoop::current() == &message_loop_);
165 provider_->message_loop()
166 ->PostTask(FROM_HERE,
167 base::Bind(&GeolocationProvider::OnLocationUpdate,
168 base::Unretained(provider_.get()),
169 position));
[email protected]baaf1842012-12-03 20:54:54170}
[email protected]90984b02012-11-30 13:00:40171
[email protected]fa7e91b82010-10-20 09:29:27172// Regression test for http://crbug.com/59377
173TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) {
[email protected]90984b02012-11-30 13:00:40174 EXPECT_FALSE(provider()->HasPermissionBeenGranted());
175 provider()->OnPermissionGranted();
176 EXPECT_TRUE(provider()->HasPermissionBeenGranted());
[email protected]fa7e91b82010-10-20 09:29:27177}
178
[email protected]b7d6acc2011-02-03 11:01:50179TEST_F(GeolocationProviderTest, StartStop) {
[email protected]90984b02012-11-30 13:00:40180 EXPECT_FALSE(provider()->IsRunning());
[email protected]b7d6acc2011-02-03 11:01:50181 NullGeolocationObserver null_observer;
182 GeolocationObserverOptions options;
[email protected]90984b02012-11-30 13:00:40183 provider()->AddObserver(&null_observer, options);
184 EXPECT_TRUE(provider()->IsRunning());
185 EXPECT_TRUE(ProvidersStarted());
[email protected]439eb402012-05-04 13:04:44186
[email protected]90984b02012-11-30 13:00:40187 provider()->RemoveObserver(&null_observer);
188 EXPECT_FALSE(ProvidersStarted());
189 EXPECT_TRUE(provider()->IsRunning());
[email protected]b7d6acc2011-02-03 11:01:50190}
191
[email protected]baaf1842012-12-03 20:54:54192TEST_F(GeolocationProviderTest, StalePositionNotSent) {
193 Geoposition first_position;
194 first_position.latitude = 12;
195 first_position.longitude = 34;
196 first_position.accuracy = 56;
197 first_position.timestamp = base::Time::Now();
198
199 AsyncMockGeolocationObserver first_observer;
200 GeolocationObserverOptions options;
201 EXPECT_CALL(first_observer, OnLocationUpdate(GeopositionEq(first_position)));
202 provider()->AddObserver(&first_observer, options);
203 SendMockLocation(first_position);
[email protected]dd32b1272013-05-04 14:17:11204 base::MessageLoop::current()->Run();
[email protected]baaf1842012-12-03 20:54:54205
206 provider()->RemoveObserver(&first_observer);
207
208 Geoposition second_position;
209 second_position.latitude = 13;
210 second_position.longitude = 34;
211 second_position.accuracy = 56;
212 second_position.timestamp = base::Time::Now();
213
214 AsyncMockGeolocationObserver second_observer;
215
216 // After adding a second observer, check that no unexpected position update
217 // is sent.
218 EXPECT_CALL(second_observer, OnLocationUpdate(testing::_)).Times(0);
219 provider()->AddObserver(&second_observer, options);
[email protected]dd32b1272013-05-04 14:17:11220 base::MessageLoop::current()->RunUntilIdle();
[email protected]baaf1842012-12-03 20:54:54221
222 // The second observer should receive the new position now.
223 EXPECT_CALL(second_observer,
224 OnLocationUpdate(GeopositionEq(second_position)));
225 SendMockLocation(second_position);
[email protected]dd32b1272013-05-04 14:17:11226 base::MessageLoop::current()->Run();
[email protected]baaf1842012-12-03 20:54:54227
228 provider()->RemoveObserver(&second_observer);
229 EXPECT_FALSE(ProvidersStarted());
230}
231
[email protected]f40000c62012-05-11 15:57:07232TEST_F(GeolocationProviderTest, OverrideLocationForTesting) {
[email protected]6bd40832012-10-29 03:01:49233 Geoposition position;
234 position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
[email protected]90984b02012-11-30 13:00:40235 provider()->OverrideLocationForTesting(position);
[email protected]439eb402012-05-04 13:04:44236 // Adding an observer when the location is overridden should synchronously
237 // update the observer with our overridden position.
[email protected]02a5fe292012-04-25 21:47:56238 MockGeolocationObserver mock_observer;
[email protected]439eb402012-05-04 13:04:44239 EXPECT_CALL(mock_observer, OnLocationUpdate(GeopositionEq(position)));
[email protected]90984b02012-11-30 13:00:40240 provider()->AddObserver(&mock_observer, GeolocationObserverOptions());
241 provider()->RemoveObserver(&mock_observer);
[email protected]d4cee672012-05-09 17:36:07242 // Wait for the providers to be stopped now that all clients are gone.
[email protected]90984b02012-11-30 13:00:40243 EXPECT_FALSE(ProvidersStarted());
[email protected]439eb402012-05-04 13:04:44244}
[email protected]02a5fe292012-04-25 21:47:56245
[email protected]439eb402012-05-04 13:04:44246TEST_F(GeolocationProviderTest, Callback) {
247 MockGeolocationCallbackWrapper callback_wrapper;
[email protected]90984b02012-11-30 13:00:40248 provider()->RequestCallback(
[email protected]439eb402012-05-04 13:04:44249 base::Bind(&MockGeolocationCallbackWrapper::Callback,
250 base::Unretained(&callback_wrapper)));
[email protected]6bd40832012-10-29 03:01:49251 Geoposition position;
[email protected]439eb402012-05-04 13:04:44252 position.latitude = 12;
253 position.longitude = 34;
254 position.accuracy = 56;
255 position.timestamp = base::Time::Now();
256 EXPECT_CALL(callback_wrapper, Callback(GeopositionEq(position)));
[email protected]90984b02012-11-30 13:00:40257 provider()->OverrideLocationForTesting(position);
[email protected]d4cee672012-05-09 17:36:07258 // Wait for the providers to be stopped now that all clients are gone.
[email protected]90984b02012-11-30 13:00:40259 EXPECT_FALSE(ProvidersStarted());
[email protected]02a5fe292012-04-25 21:47:56260}
261
[email protected]6bd40832012-10-29 03:01:49262} // namespace content