16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "content/browser/geolocation/geolocation_provider_impl.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/geolocation/mock_location_arbitrator.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/access_token_store.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::MakeMatcher;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Matcher;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::MatcherInterface;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::MatchResultListener;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class LocationProviderForTestArbitrator : public GeolocationProviderImpl {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LocationProviderForTestArbitrator() : mock_arbitrator_(NULL) {}
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~LocationProviderForTestArbitrator() {}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only valid for use on the geolocation thread.
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MockLocationArbitrator* mock_arbitrator() const {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return mock_arbitrator_;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // GeolocationProviderImpl implementation:
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual LocationArbitrator* CreateArbitrator() OVERRIDE;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MockLocationArbitrator* mock_arbitrator_;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)LocationArbitrator* LocationProviderForTestArbitrator::CreateArbitrator() {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(mock_arbitrator_ == NULL);
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  mock_arbitrator_ = new MockLocationArbitrator;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return mock_arbitrator_;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class GeolocationObserver {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual ~GeolocationObserver() {}
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual void OnLocationUpdate(const Geoposition& position) = 0;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockGeolocationObserver : public GeolocationObserver {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(OnLocationUpdate, void(const Geoposition& position));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AsyncMockGeolocationObserver : public MockGeolocationObserver {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnLocationUpdate(const Geoposition& position) OVERRIDE {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockGeolocationObserver::OnLocationUpdate(position);
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->Quit();
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockGeolocationCallbackWrapper {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(Callback, void(const Geoposition& position));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GeopositionEqMatcher
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public MatcherInterface<const Geoposition&> {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit GeopositionEqMatcher(const Geoposition& expected)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : expected_(expected) {}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool MatchAndExplain(const Geoposition& actual,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               MatchResultListener* listener) const OVERRIDE {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return actual.latitude == expected_.latitude &&
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           actual.longitude == expected_.longitude &&
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           actual.altitude == expected_.altitude &&
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           actual.accuracy == expected_.accuracy &&
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           actual.altitude_accuracy == expected_.altitude_accuracy &&
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           actual.heading == expected_.heading &&
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           actual.speed == expected_.speed &&
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           actual.timestamp == expected_.timestamp &&
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           actual.error_code == expected_.error_code &&
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           actual.error_message == expected_.error_message;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DescribeTo(::std::ostream* os) const OVERRIDE {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *os << "which matches the expected position";
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void DescribeNegationTo(::std::ostream* os) const OVERRIDE {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *os << "which does not match the expected position";
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Geoposition expected_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GeopositionEqMatcher);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return MakeMatcher(new GeopositionEqMatcher(expected));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GeolocationProviderTest : public testing::Test {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GeolocationProviderTest()
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : message_loop_(),
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ui_thread_(BrowserThread::UI, &message_loop_),
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        provider_(new LocationProviderForTestArbitrator) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~GeolocationProviderTest() {}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LocationProviderForTestArbitrator* provider() { return provider_.get(); }
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called on test thread.
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ProvidersStarted();
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SendMockLocation(const Geoposition& position);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called on provider thread.
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetProvidersStarted(bool* started);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop message_loop_;
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestBrowserThread ui_thread_;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LocationProviderForTestArbitrator> provider_;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GeolocationProviderTest::ProvidersStarted() {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(provider_->IsRunning());
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == &message_loop_);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool started;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  provider_->message_loop_proxy()->PostTaskAndReply(
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&GeolocationProviderTest::GetProvidersStarted,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this),
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 &started),
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoop::QuitClosure());
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.Run();
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return started;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GeolocationProviderTest::GetProvidersStarted(bool* started) {
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == provider_->message_loop());
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *started = provider_->mock_arbitrator()->providers_started();
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GeolocationProviderTest::SendMockLocation(const Geoposition& position) {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(provider_->IsRunning());
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == &message_loop_);
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  provider_->message_loop()
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ->PostTask(FROM_HERE,
163b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 base::Bind(&GeolocationProviderImpl::OnLocationUpdate,
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            base::Unretained(provider_.get()),
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            position));
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Regression test for http://crbug.com/59377
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) {
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(provider()->user_did_opt_into_location_services_for_testing());
171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  provider()->UserDidOptIntoLocationServices();
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(provider()->user_did_opt_into_location_services_for_testing());
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DummyFunction(const Geoposition& position) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationProviderTest, StartStop) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(provider()->IsRunning());
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GeolocationProviderImpl::LocationUpdateCallback callback =
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&DummyFunction);
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<content::GeolocationProvider::Subscription> subscription =
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      provider()->AddLocationUpdateCallback(callback, false);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(provider()->IsRunning());
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(ProvidersStarted());
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  subscription.reset();
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(ProvidersStarted());
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(provider()->IsRunning());
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(GeolocationProviderTest, StalePositionNotSent) {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Geoposition first_position;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first_position.latitude = 12;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first_position.longitude = 34;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first_position.accuracy = 56;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first_position.timestamp = base::Time::Now();
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AsyncMockGeolocationObserver first_observer;
201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  GeolocationProviderImpl::LocationUpdateCallback first_callback = base::Bind(
202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      &MockGeolocationObserver::OnLocationUpdate,
203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Unretained(&first_observer));
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(first_observer, OnLocationUpdate(GeopositionEq(first_position)));
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<content::GeolocationProvider::Subscription> subscription =
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      provider()->AddLocationUpdateCallback(first_callback, false);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendMockLocation(first_position);
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->Run();
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  subscription.reset();
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Geoposition second_position;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  second_position.latitude = 13;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  second_position.longitude = 34;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  second_position.accuracy = 56;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  second_position.timestamp = base::Time::Now();
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AsyncMockGeolocationObserver second_observer;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // After adding a second observer, check that no unexpected position update
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is sent.
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(second_observer, OnLocationUpdate(testing::_)).Times(0);
223b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  GeolocationProviderImpl::LocationUpdateCallback second_callback = base::Bind(
224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      &MockGeolocationObserver::OnLocationUpdate,
225b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Unretained(&second_observer));
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<content::GeolocationProvider::Subscription> subscription2 =
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      provider()->AddLocationUpdateCallback(second_callback, false);
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The second observer should receive the new position now.
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(second_observer,
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              OnLocationUpdate(GeopositionEq(second_position)));
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendMockLocation(second_position);
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->Run();
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  subscription2.reset();
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(ProvidersStarted());
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationProviderTest, OverrideLocationForTesting) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Geoposition position;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  provider()->OverrideLocationForTesting(position);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adding an observer when the location is overridden should synchronously
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // update the observer with our overridden position.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockGeolocationObserver mock_observer;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(mock_observer, OnLocationUpdate(GeopositionEq(position)));
248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  GeolocationProviderImpl::LocationUpdateCallback callback = base::Bind(
249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      &MockGeolocationObserver::OnLocationUpdate,
250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Unretained(&mock_observer));
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<content::GeolocationProvider::Subscription> subscription =
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      provider()->AddLocationUpdateCallback(callback, false);
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  subscription.reset();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the providers to be stopped now that all clients are gone.
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(ProvidersStarted());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
259