Commit d04d18d7 authored by lethalantidote's avatar lethalantidote Committed by Commit bot

Gets rid of the LocationArbitrator interface, in preference for LocationProvider.

This CL reorganizes classes that derived from LocationArbitrator to instead
derive from LocationProvider. There was a quite a bit of overlap between the
two interfaces, and merging the two in favor of LocationProvider makes later
work with Blimp much easier.

Other work included:
*Addresses TODO to remove CreateArbitrator in favor of SetArbitratorForTest

BUG=614486, 637869

Review-Url: https://codereview.chromium.org/2226143002
Cr-Commit-Position: refs/heads/master@{#414735}
parent dca0b3af
...@@ -44,21 +44,17 @@ void BlimpLocationProvider::StopProvider() { ...@@ -44,21 +44,17 @@ void BlimpLocationProvider::StopProvider() {
} }
} }
void BlimpLocationProvider::GetPosition(device::Geoposition* position) { const device::Geoposition& BlimpLocationProvider::GetPosition() {
*position = cached_position_; return cached_position_;
} }
void BlimpLocationProvider::RequestRefresh() { void BlimpLocationProvider::OnPermissionGranted() {
DCHECK(is_started_); DCHECK(is_started_);
if (delegate_) { if (delegate_) {
delegate_->RequestRefresh(); delegate_->RequestRefresh();
} }
} }
void BlimpLocationProvider::OnPermissionGranted() {
RequestRefresh();
}
void BlimpLocationProvider::SetUpdateCallback( void BlimpLocationProvider::SetUpdateCallback(
const LocationProviderUpdateCallback& callback) { const LocationProviderUpdateCallback& callback) {
if (delegate_) { if (delegate_) {
......
...@@ -37,8 +37,7 @@ class BlimpLocationProvider : public device::LocationProvider { ...@@ -37,8 +37,7 @@ class BlimpLocationProvider : public device::LocationProvider {
// device::LocationProvider implementation. // device::LocationProvider implementation.
bool StartProvider(bool high_accuracy) override; bool StartProvider(bool high_accuracy) override;
void StopProvider() override; void StopProvider() override;
void GetPosition(device::Geoposition* position) override; const device::Geoposition& GetPosition() override;
void RequestRefresh() override;
void OnPermissionGranted() override; void OnPermissionGranted() override;
void SetUpdateCallback( void SetUpdateCallback(
const LocationProviderUpdateCallback& callback) override; const LocationProviderUpdateCallback& callback) override;
......
...@@ -106,22 +106,7 @@ TEST_F(BlimpLocationProviderTest, LocationProviderDeleted) { ...@@ -106,22 +106,7 @@ TEST_F(BlimpLocationProviderTest, LocationProviderDeleted) {
location_provider_.reset(); location_provider_.reset();
} }
TEST_F(BlimpLocationProviderTest, RequestRefreshRunsCorrectly) { TEST_F(BlimpLocationProviderTest, OnPermissionGranted) {
EXPECT_CALL(*delegate_, RequestRefresh()).Times(1);
location_provider_->StartProvider(true);
location_provider_->RequestRefresh();
}
TEST_F(BlimpLocationProviderTest, RequestRefreshHandlesNullDelegate) {
EXPECT_CALL(*delegate_, RequestRefresh()).Times(0);
location_provider_->StartProvider(true);
delegate_.reset();
location_provider_->RequestRefresh();
}
TEST_F(BlimpLocationProviderTest, OnPermissionGrantedCallsRefresh) {
EXPECT_CALL(*delegate_, RequestRefresh()).Times(1); EXPECT_CALL(*delegate_, RequestRefresh()).Times(1);
location_provider_->StartProvider(true); location_provider_->StartProvider(true);
......
...@@ -180,7 +180,8 @@ TEST_F(EngineGeolocationFeatureTest, UnexpectedMessageReceived) { ...@@ -180,7 +180,8 @@ TEST_F(EngineGeolocationFeatureTest, UnexpectedMessageReceived) {
EXPECT_EQ(net::ERR_UNEXPECTED, cb.WaitForResult()); EXPECT_EQ(net::ERR_UNEXPECTED, cb.WaitForResult());
} }
TEST_F(EngineGeolocationFeatureTest, RequestRefresh) { TEST_F(EngineGeolocationFeatureTest,
OnPermissionGrantedTriggersRefreshRequest) {
EXPECT_CALL(*out_processor_, EXPECT_CALL(*out_processor_,
MockableProcessMessage( MockableProcessMessage(
EqualsUpdatedRequestLevel( EqualsUpdatedRequestLevel(
...@@ -199,7 +200,7 @@ TEST_F(EngineGeolocationFeatureTest, RequestRefresh) { ...@@ -199,7 +200,7 @@ TEST_F(EngineGeolocationFeatureTest, RequestRefresh) {
.Times(1); .Times(1);
location_provider_->StartProvider(true); location_provider_->StartProvider(true);
location_provider_->RequestRefresh(); location_provider_->OnPermissionGranted();
} }
} // namespace engine } // namespace engine
......
...@@ -31,7 +31,6 @@ component("device_geolocation") { ...@@ -31,7 +31,6 @@ component("device_geolocation") {
"geoposition.h", "geoposition.h",
"location_api_adapter_android.cc", "location_api_adapter_android.cc",
"location_api_adapter_android.h", "location_api_adapter_android.h",
"location_arbitrator.h",
"location_arbitrator_impl.cc", "location_arbitrator_impl.cc",
"location_arbitrator_impl.h", "location_arbitrator_impl.h",
"location_provider.h", "location_provider.h",
...@@ -155,8 +154,6 @@ source_set("unittests") { ...@@ -155,8 +154,6 @@ source_set("unittests") {
"fake_access_token_store.h", "fake_access_token_store.h",
"geolocation_provider_impl_unittest.cc", "geolocation_provider_impl_unittest.cc",
"location_arbitrator_impl_unittest.cc", "location_arbitrator_impl_unittest.cc",
"mock_location_arbitrator.cc",
"mock_location_arbitrator.h",
"mock_location_provider.cc", "mock_location_provider.cc",
"mock_location_provider.h", "mock_location_provider.h",
"network_location_provider_unittest.cc", "network_location_provider_unittest.cc",
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "device/geolocation/geolocation_provider_impl.h" #include "device/geolocation/geolocation_provider_impl.h"
#include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/callback.h" #include "base/callback.h"
...@@ -72,7 +74,8 @@ void GeolocationProviderImpl::OverrideLocationForTesting( ...@@ -72,7 +74,8 @@ void GeolocationProviderImpl::OverrideLocationForTesting(
NotifyClients(position); NotifyClients(position);
} }
void GeolocationProviderImpl::OnLocationUpdate(const Geoposition& position) { void GeolocationProviderImpl::OnLocationUpdate(const LocationProvider* provider,
const Geoposition& position) {
DCHECK(OnGeolocationThread()); DCHECK(OnGeolocationThread());
// Will be true only in testing. // Will be true only in testing.
if (ignore_location_updates_) if (ignore_location_updates_)
...@@ -104,6 +107,11 @@ GeolocationProviderImpl::~GeolocationProviderImpl() { ...@@ -104,6 +107,11 @@ GeolocationProviderImpl::~GeolocationProviderImpl() {
DCHECK(!arbitrator_); DCHECK(!arbitrator_);
} }
void GeolocationProviderImpl::SetArbitratorForTesting(
std::unique_ptr<LocationProvider> arbitrator) {
arbitrator_ = std::move(arbitrator);
}
bool GeolocationProviderImpl::OnGeolocationThread() const { bool GeolocationProviderImpl::OnGeolocationThread() const {
return task_runner()->BelongsToCurrentThread(); return task_runner()->BelongsToCurrentThread();
} }
...@@ -140,13 +148,13 @@ void GeolocationProviderImpl::OnClientsChanged() { ...@@ -140,13 +148,13 @@ void GeolocationProviderImpl::OnClientsChanged() {
void GeolocationProviderImpl::StopProviders() { void GeolocationProviderImpl::StopProviders() {
DCHECK(OnGeolocationThread()); DCHECK(OnGeolocationThread());
DCHECK(arbitrator_); DCHECK(arbitrator_);
arbitrator_->StopProviders(); arbitrator_->StopProvider();
} }
void GeolocationProviderImpl::StartProviders(bool enable_high_accuracy) { void GeolocationProviderImpl::StartProviders(bool enable_high_accuracy) {
DCHECK(OnGeolocationThread()); DCHECK(OnGeolocationThread());
DCHECK(arbitrator_); DCHECK(arbitrator_);
arbitrator_->StartProviders(enable_high_accuracy); arbitrator_->StartProvider(enable_high_accuracy);
} }
void GeolocationProviderImpl::InformProvidersPermissionGranted() { void GeolocationProviderImpl::InformProvidersPermissionGranted() {
...@@ -174,25 +182,23 @@ void GeolocationProviderImpl::NotifyClients(const Geoposition& position) { ...@@ -174,25 +182,23 @@ void GeolocationProviderImpl::NotifyClients(const Geoposition& position) {
void GeolocationProviderImpl::Init() { void GeolocationProviderImpl::Init() {
DCHECK(OnGeolocationThread()); DCHECK(OnGeolocationThread());
DCHECK(!arbitrator_);
arbitrator_ = CreateArbitrator();
}
void GeolocationProviderImpl::CleanUp() { if (!arbitrator_) {
DCHECK(OnGeolocationThread()); LocationProvider::LocationProviderUpdateCallback callback = base::Bind(
arbitrator_.reset();
}
std::unique_ptr<LocationArbitrator>
GeolocationProviderImpl::CreateArbitrator() {
LocationArbitratorImpl::LocationUpdateCallback callback = base::Bind(
&GeolocationProviderImpl::OnLocationUpdate, base::Unretained(this)); &GeolocationProviderImpl::OnLocationUpdate, base::Unretained(this));
// Use the embedder's |g_delegate| or fall back to the default one. // Use the embedder's |g_delegate| or fall back to the default one.
if (!g_delegate.Get()) if (!g_delegate.Get())
g_delegate.Get().reset(new GeolocationDelegate); g_delegate.Get().reset(new GeolocationDelegate);
return base::MakeUnique<LocationArbitratorImpl>(callback, arbitrator_ =
g_delegate.Get().get()); base::MakeUnique<LocationArbitratorImpl>(g_delegate.Get().get());
arbitrator_->SetUpdateCallback(callback);
}
}
void GeolocationProviderImpl::CleanUp() {
DCHECK(OnGeolocationThread());
arbitrator_.reset();
} }
} // namespace device } // namespace device
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "device/geolocation/geolocation_export.h" #include "device/geolocation/geolocation_export.h"
#include "device/geolocation/geolocation_provider.h" #include "device/geolocation/geolocation_provider.h"
#include "device/geolocation/geoposition.h" #include "device/geolocation/geoposition.h"
#include "device/geolocation/location_provider.h"
namespace base { namespace base {
template <typename Type> template <typename Type>
...@@ -24,7 +25,6 @@ class SingleThreadTaskRunner; ...@@ -24,7 +25,6 @@ class SingleThreadTaskRunner;
} }
namespace device { namespace device {
class LocationArbitrator;
class DEVICE_GEOLOCATION_EXPORT GeolocationProviderImpl class DEVICE_GEOLOCATION_EXPORT GeolocationProviderImpl
: public NON_EXPORTED_BASE(GeolocationProvider), : public NON_EXPORTED_BASE(GeolocationProvider),
...@@ -38,7 +38,8 @@ class DEVICE_GEOLOCATION_EXPORT GeolocationProviderImpl ...@@ -38,7 +38,8 @@ class DEVICE_GEOLOCATION_EXPORT GeolocationProviderImpl
void OverrideLocationForTesting(const Geoposition& position) override; void OverrideLocationForTesting(const Geoposition& position) override;
// Callback from the LocationArbitrator. Public for testing. // Callback from the LocationArbitrator. Public for testing.
void OnLocationUpdate(const Geoposition& position); void OnLocationUpdate(const LocationProvider* provider,
const Geoposition& position);
// Gets a pointer to the singleton instance of the location relayer, which // Gets a pointer to the singleton instance of the location relayer, which
// is in turn bound to the browser's global context objects. This must only be // is in turn bound to the browser's global context objects. This must only be
...@@ -50,16 +51,15 @@ class DEVICE_GEOLOCATION_EXPORT GeolocationProviderImpl ...@@ -50,16 +51,15 @@ class DEVICE_GEOLOCATION_EXPORT GeolocationProviderImpl
return user_did_opt_into_location_services_; return user_did_opt_into_location_services_;
} }
protected: // Safe to call while there are no GeolocationProviderImpl clients
// registered.
void SetArbitratorForTesting(std::unique_ptr<LocationProvider> arbitrator);
private:
friend struct base::DefaultSingletonTraits<GeolocationProviderImpl>; friend struct base::DefaultSingletonTraits<GeolocationProviderImpl>;
GeolocationProviderImpl(); GeolocationProviderImpl();
~GeolocationProviderImpl() override; ~GeolocationProviderImpl() override;
// Useful for injecting mock geolocation arbitrator in tests.
// TODO(mvanouwerkerk): Use something like SetArbitratorForTesting instead.
virtual std::unique_ptr<LocationArbitrator> CreateArbitrator();
private:
bool OnGeolocationThread() const; bool OnGeolocationThread() const;
// Start and stop providers as needed when clients are added or removed. // Start and stop providers as needed when clients are added or removed.
...@@ -93,12 +93,12 @@ class DEVICE_GEOLOCATION_EXPORT GeolocationProviderImpl ...@@ -93,12 +93,12 @@ class DEVICE_GEOLOCATION_EXPORT GeolocationProviderImpl
// True only in testing, where we want to use a custom position. // True only in testing, where we want to use a custom position.
bool ignore_location_updates_; bool ignore_location_updates_;
// Only to be used on the geolocation thread. // Used to PostTask()s from the geolocation thread to caller thread.
std::unique_ptr<LocationArbitrator> arbitrator_;
// Used to PostTask()s from the geolocation thread to creation thread.
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
// Only to be used on the geolocation thread.
std::unique_ptr<LocationProvider> arbitrator_;
DISALLOW_COPY_AND_ASSIGN(GeolocationProviderImpl); DISALLOW_COPY_AND_ASSIGN(GeolocationProviderImpl);
}; };
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <memory> #include <memory>
#include "base/at_exit.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/location.h" #include "base/location.h"
...@@ -17,7 +18,7 @@ ...@@ -17,7 +18,7 @@
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "device/geolocation/access_token_store.h" #include "device/geolocation/access_token_store.h"
#include "device/geolocation/mock_location_arbitrator.h" #include "device/geolocation/mock_location_provider.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -27,30 +28,7 @@ using testing::MatcherInterface; ...@@ -27,30 +28,7 @@ using testing::MatcherInterface;
using testing::MatchResultListener; using testing::MatchResultListener;
namespace device { namespace device {
namespace {
class LocationProviderForTestArbitrator : public GeolocationProviderImpl {
public:
LocationProviderForTestArbitrator() : mock_arbitrator_(NULL) {}
~LocationProviderForTestArbitrator() override {}
// Only valid for use on the geolocation thread.
MockLocationArbitrator* mock_arbitrator() const { return mock_arbitrator_; }
protected:
// GeolocationProviderImpl implementation:
std::unique_ptr<LocationArbitrator> CreateArbitrator() override;
private:
// An alias to the arbitrator stored in the super class, where it is owned.
MockLocationArbitrator* mock_arbitrator_;
};
std::unique_ptr<LocationArbitrator>
LocationProviderForTestArbitrator::CreateArbitrator() {
DCHECK(mock_arbitrator_ == NULL);
mock_arbitrator_ = new MockLocationArbitrator;
return base::WrapUnique(mock_arbitrator_);
}
class GeolocationObserver { class GeolocationObserver {
public: public:
...@@ -113,14 +91,24 @@ Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) { ...@@ -113,14 +91,24 @@ Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) {
return MakeMatcher(new GeopositionEqMatcher(expected)); return MakeMatcher(new GeopositionEqMatcher(expected));
} }
void DummyFunction(const LocationProvider* provider,
const Geoposition& position) {}
} // namespace
class GeolocationProviderTest : public testing::Test { class GeolocationProviderTest : public testing::Test {
protected: protected:
GeolocationProviderTest() GeolocationProviderTest() : arbitrator_(new MockLocationProvider) {
: message_loop_(), provider_(new LocationProviderForTestArbitrator) {} provider()->SetArbitratorForTesting(base::WrapUnique(arbitrator_));
}
~GeolocationProviderTest() override {} ~GeolocationProviderTest() override {}
LocationProviderForTestArbitrator* provider() { return provider_.get(); } GeolocationProviderImpl* provider() {
return GeolocationProviderImpl::GetInstance();
}
MockLocationProvider* arbitrator() { return arbitrator_; }
// Called on test thread. // Called on test thread.
bool ProvidersStarted(); bool ProvidersStarted();
...@@ -130,15 +118,25 @@ class GeolocationProviderTest : public testing::Test { ...@@ -130,15 +118,25 @@ class GeolocationProviderTest : public testing::Test {
// Called on provider thread. // Called on provider thread.
void GetProvidersStarted(bool* started); void GetProvidersStarted(bool* started);
// |at_exit| must be initialized before all other variables so that it is
// available to register with Singletons and can handle tear down when the
// test completes.
base::ShadowingAtExitManager at_exit_;
base::MessageLoopForUI message_loop_; base::MessageLoopForUI message_loop_;
std::unique_ptr<LocationProviderForTestArbitrator> provider_;
// Owned by the GeolocationProviderImpl class.
MockLocationProvider* arbitrator_;
DISALLOW_COPY_AND_ASSIGN(GeolocationProviderTest);
}; };
bool GeolocationProviderTest::ProvidersStarted() { bool GeolocationProviderTest::ProvidersStarted() {
DCHECK(provider_->IsRunning()); DCHECK(provider()->IsRunning());
DCHECK(base::MessageLoop::current() == &message_loop_); DCHECK(base::MessageLoop::current() == &message_loop_);
bool started; bool started;
provider_->task_runner()->PostTaskAndReply( provider()->task_runner()->PostTaskAndReply(
FROM_HERE, base::Bind(&GeolocationProviderTest::GetProvidersStarted, FROM_HERE, base::Bind(&GeolocationProviderTest::GetProvidersStarted,
base::Unretained(this), &started), base::Unretained(this), &started),
base::MessageLoop::QuitWhenIdleClosure()); base::MessageLoop::QuitWhenIdleClosure());
...@@ -147,33 +145,35 @@ bool GeolocationProviderTest::ProvidersStarted() { ...@@ -147,33 +145,35 @@ bool GeolocationProviderTest::ProvidersStarted() {
} }
void GeolocationProviderTest::GetProvidersStarted(bool* started) { void GeolocationProviderTest::GetProvidersStarted(bool* started) {
DCHECK(provider_->task_runner()->BelongsToCurrentThread()); DCHECK(provider()->task_runner()->BelongsToCurrentThread());
*started = provider_->mock_arbitrator()->providers_started(); *started = arbitrator()->is_started();
} }
void GeolocationProviderTest::SendMockLocation(const Geoposition& position) { void GeolocationProviderTest::SendMockLocation(const Geoposition& position) {
DCHECK(provider_->IsRunning()); DCHECK(provider()->IsRunning());
DCHECK(base::MessageLoop::current() == &message_loop_); DCHECK(base::MessageLoop::current() == &message_loop_);
provider_->task_runner()->PostTask( provider()->task_runner()->PostTask(
FROM_HERE, base::Bind(&GeolocationProviderImpl::OnLocationUpdate, FROM_HERE,
base::Unretained(provider_.get()), position)); base::Bind(&GeolocationProviderImpl::OnLocationUpdate,
base::Unretained(provider()), arbitrator_, position));
} }
// Regression test for http://crbug.com/59377 // Regression test for http://crbug.com/59377
TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) { TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) {
// Clear |provider|'s arbitrator so the default arbitrator can be used.
provider()->SetArbitratorForTesting(nullptr);
EXPECT_FALSE(provider()->user_did_opt_into_location_services_for_testing()); EXPECT_FALSE(provider()->user_did_opt_into_location_services_for_testing());
provider()->UserDidOptIntoLocationServices(); provider()->UserDidOptIntoLocationServices();
EXPECT_TRUE(provider()->user_did_opt_into_location_services_for_testing()); EXPECT_TRUE(provider()->user_did_opt_into_location_services_for_testing());
} }
void DummyFunction(const Geoposition& position) {}
TEST_F(GeolocationProviderTest, StartStop) { TEST_F(GeolocationProviderTest, StartStop) {
EXPECT_FALSE(provider()->IsRunning()); EXPECT_FALSE(provider()->IsRunning());
GeolocationProviderImpl::LocationUpdateCallback callback = LocationProvider::LocationProviderUpdateCallback callback =
base::Bind(&DummyFunction); base::Bind(&DummyFunction);
std::unique_ptr<GeolocationProvider::Subscription> subscription = std::unique_ptr<GeolocationProvider::Subscription> subscription =
provider()->AddLocationUpdateCallback(callback, false); provider()->AddLocationUpdateCallback(base::Bind(callback, arbitrator()),
false);
EXPECT_TRUE(provider()->IsRunning()); EXPECT_TRUE(provider()->IsRunning());
EXPECT_TRUE(ProvidersStarted()); EXPECT_TRUE(ProvidersStarted());
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_GEOLOCATION_LOCATION_ARBITRATOR_H_
#define DEVICE_GEOLOCATION_LOCATION_ARBITRATOR_H_
#include "device/geolocation/geolocation_export.h"
namespace device {
// This class is responsible for handling updates from multiple underlying
// providers and resolving them to a single 'best' location fix at any given
// moment.
class DEVICE_GEOLOCATION_EXPORT LocationArbitrator {
public:
virtual ~LocationArbitrator(){};
// See more details in geolocation_provider.
virtual void StartProviders(bool enable_high_accuracy) = 0;
virtual void StopProviders() = 0;
// Called everytime permission is granted to a page for using geolocation.
// This may either be through explicit user action (e.g. responding to the
// infobar prompt) or inferred from a persisted site permission.
// The arbitrator will inform all providers of this, which may in turn use
// this information to modify their internal policy.
virtual void OnPermissionGranted() = 0;
// Returns true if this arbitrator has received at least one call to
// OnPermissionGranted().
virtual bool HasPermissionBeenGranted() const = 0;
};
} // namespace device
#endif // DEVICE_GEOLOCATION_LOCATION_ARBITRATOR_H_
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include "device/geolocation/location_arbitrator_impl.h" #include "device/geolocation/location_arbitrator_impl.h"
#include <map> #include <map>
#include <memory>
#include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
...@@ -28,13 +30,8 @@ const int64_t LocationArbitratorImpl::kFixStaleTimeoutMilliseconds = ...@@ -28,13 +30,8 @@ const int64_t LocationArbitratorImpl::kFixStaleTimeoutMilliseconds =
11 * base::Time::kMillisecondsPerSecond; 11 * base::Time::kMillisecondsPerSecond;
LocationArbitratorImpl::LocationArbitratorImpl( LocationArbitratorImpl::LocationArbitratorImpl(
const LocationUpdateCallback& callback,
GeolocationDelegate* delegate) GeolocationDelegate* delegate)
: delegate_(delegate), : delegate_(delegate),
arbitrator_update_callback_(callback),
provider_update_callback_(
base::Bind(&LocationArbitratorImpl::OnLocationUpdate,
base::Unretained(this))),
position_provider_(nullptr), position_provider_(nullptr),
is_permission_granted_(false), is_permission_granted_(false),
is_running_(false) {} is_running_(false) {}
...@@ -45,13 +42,17 @@ GURL LocationArbitratorImpl::DefaultNetworkProviderURL() { ...@@ -45,13 +42,17 @@ GURL LocationArbitratorImpl::DefaultNetworkProviderURL() {
return GURL(kDefaultNetworkProviderUrl); return GURL(kDefaultNetworkProviderUrl);
} }
bool LocationArbitratorImpl::HasPermissionBeenGrantedForTest() const {
return is_permission_granted_;
}
void LocationArbitratorImpl::OnPermissionGranted() { void LocationArbitratorImpl::OnPermissionGranted() {
is_permission_granted_ = true; is_permission_granted_ = true;
for (const auto& provider : providers_) for (const auto& provider : providers_)
provider->OnPermissionGranted(); provider->OnPermissionGranted();
} }
void LocationArbitratorImpl::StartProviders(bool enable_high_accuracy) { bool LocationArbitratorImpl::StartProvider(bool enable_high_accuracy) {
// Stash options as OnAccessTokenStoresLoaded has not yet been called. // Stash options as OnAccessTokenStoresLoaded has not yet been called.
is_running_ = true; is_running_ = true;
enable_high_accuracy_ = enable_high_accuracy; enable_high_accuracy_ = enable_high_accuracy;
...@@ -67,26 +68,29 @@ void LocationArbitratorImpl::StartProviders(bool enable_high_accuracy) { ...@@ -67,26 +68,29 @@ void LocationArbitratorImpl::StartProviders(bool enable_high_accuracy) {
base::Bind(&LocationArbitratorImpl::OnAccessTokenStoresLoaded, base::Bind(&LocationArbitratorImpl::OnAccessTokenStoresLoaded,
base::Unretained(this))); base::Unretained(this)));
access_token_store->LoadAccessTokens(token_store_callback_.callback()); access_token_store->LoadAccessTokens(token_store_callback_.callback());
return; return true;
} }
} }
DoStartProviders(); return DoStartProviders();
} }
void LocationArbitratorImpl::DoStartProviders() { bool LocationArbitratorImpl::DoStartProviders() {
if (providers_.empty()) { if (providers_.empty()) {
// If no providers are available, we report an error to avoid // If no providers are available, we report an error to avoid
// callers waiting indefinitely for a reply. // callers waiting indefinitely for a reply.
Geoposition position; Geoposition position;
position.error_code = Geoposition::ERROR_CODE_PERMISSION_DENIED; position.error_code = Geoposition::ERROR_CODE_PERMISSION_DENIED;
arbitrator_update_callback_.Run(position); arbitrator_update_callback_.Run(this, position);
return; return false;
} }
for (const auto& provider : providers_) bool started = false;
provider->StartProvider(enable_high_accuracy_); for (const auto& provider : providers_) {
started = provider->StartProvider(enable_high_accuracy_) || started;
}
return started;
} }
void LocationArbitratorImpl::StopProviders() { void LocationArbitratorImpl::StopProvider() {
// Reset the reference location state (provider+position) // Reset the reference location state (provider+position)
// so that future starts use fresh locations from // so that future starts use fresh locations from
// the newly constructed providers. // the newly constructed providers.
...@@ -114,7 +118,8 @@ void LocationArbitratorImpl::RegisterProvider( ...@@ -114,7 +118,8 @@ void LocationArbitratorImpl::RegisterProvider(
std::unique_ptr<LocationProvider> provider) { std::unique_ptr<LocationProvider> provider) {
if (!provider) if (!provider)
return; return;
provider->SetUpdateCallback(provider_update_callback_); provider->SetUpdateCallback(base::Bind(
&LocationArbitratorImpl::OnLocationUpdate, base::Unretained(this)));
if (is_permission_granted_) if (is_permission_granted_)
provider->OnPermissionGranted(); provider->OnPermissionGranted();
providers_.push_back(std::move(provider)); providers_.push_back(std::move(provider));
...@@ -137,7 +142,17 @@ void LocationArbitratorImpl::OnLocationUpdate(const LocationProvider* provider, ...@@ -137,7 +142,17 @@ void LocationArbitratorImpl::OnLocationUpdate(const LocationProvider* provider,
return; return;
position_provider_ = provider; position_provider_ = provider;
position_ = new_position; position_ = new_position;
arbitrator_update_callback_.Run(position_); arbitrator_update_callback_.Run(this, position_);
}
const Geoposition& LocationArbitratorImpl::GetPosition() {
return position_;
}
void LocationArbitratorImpl::SetUpdateCallback(
const LocationProviderUpdateCallback& callback) {
DCHECK(!callback.is_null());
arbitrator_update_callback_ = callback;
} }
scoped_refptr<AccessTokenStore> LocationArbitratorImpl::NewAccessTokenStore() { scoped_refptr<AccessTokenStore> LocationArbitratorImpl::NewAccessTokenStore() {
...@@ -205,8 +220,4 @@ bool LocationArbitratorImpl::IsNewPositionBetter( ...@@ -205,8 +220,4 @@ bool LocationArbitratorImpl::IsNewPositionBetter(
return false; return false;
} }
bool LocationArbitratorImpl::HasPermissionBeenGranted() const {
return is_permission_granted_;
}
} // namespace device } // namespace device
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define DEVICE_GEOLOCATION_LOCATION_ARBITRATOR_IMPL_H_ #define DEVICE_GEOLOCATION_LOCATION_ARBITRATOR_IMPL_H_
#include <stdint.h> #include <stdint.h>
#include <memory>
#include <vector> #include <vector>
#include "base/callback_forward.h" #include "base/callback_forward.h"
...@@ -18,7 +19,6 @@ ...@@ -18,7 +19,6 @@
#include "device/geolocation/geolocation_export.h" #include "device/geolocation/geolocation_export.h"
#include "device/geolocation/geolocation_provider.h" #include "device/geolocation/geolocation_provider.h"
#include "device/geolocation/geoposition.h" #include "device/geolocation/geoposition.h"
#include "device/geolocation/location_arbitrator.h"
#include "device/geolocation/location_provider.h" #include "device/geolocation/location_provider.h"
#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_context_getter.h"
...@@ -35,26 +35,26 @@ class LocationProvider; ...@@ -35,26 +35,26 @@ class LocationProvider;
// providers and resolving them to a single 'best' location fix at any given // providers and resolving them to a single 'best' location fix at any given
// moment. // moment.
class DEVICE_GEOLOCATION_EXPORT LocationArbitratorImpl class DEVICE_GEOLOCATION_EXPORT LocationArbitratorImpl
: public LocationArbitrator { : public LocationProvider {
public: public:
// Number of milliseconds newer a location provider has to be that it's worth // Number of milliseconds newer a location provider has to be that it's worth
// switching to this location provider on the basis of it being fresher // switching to this location provider on the basis of it being fresher
// (regardles of relative accuracy). Public for tests. // (regardles of relative accuracy). Public for tests.
static const int64_t kFixStaleTimeoutMilliseconds; static const int64_t kFixStaleTimeoutMilliseconds;
typedef base::Callback<void(const Geoposition&)> LocationUpdateCallback; explicit LocationArbitratorImpl(GeolocationDelegate* delegate);
LocationArbitratorImpl(const LocationUpdateCallback& callback,
GeolocationDelegate* delegate);
~LocationArbitratorImpl() override; ~LocationArbitratorImpl() override;
static GURL DefaultNetworkProviderURL(); static GURL DefaultNetworkProviderURL();
bool HasPermissionBeenGrantedForTest() const;
// LocationArbitrator
void StartProviders(bool enable_high_accuracy) override; // LocationProvider implementation.
void StopProviders() override; void SetUpdateCallback(
const LocationProviderUpdateCallback& callback) override;
bool StartProvider(bool enable_high_accuracy) override;
void StopProvider() override;
const Geoposition& GetPosition() override;
void OnPermissionGranted() override; void OnPermissionGranted() override;
bool HasPermissionBeenGranted() const override;
protected: protected:
// These functions are useful for injection of dependencies in derived // These functions are useful for injection of dependencies in derived
...@@ -81,7 +81,7 @@ class DEVICE_GEOLOCATION_EXPORT LocationArbitratorImpl ...@@ -81,7 +81,7 @@ class DEVICE_GEOLOCATION_EXPORT LocationArbitratorImpl
void OnAccessTokenStoresLoaded( void OnAccessTokenStoresLoaded(
AccessTokenStore::AccessTokenMap access_token_map, AccessTokenStore::AccessTokenMap access_token_map,
const scoped_refptr<net::URLRequestContextGetter>& context_getter); const scoped_refptr<net::URLRequestContextGetter>& context_getter);
void DoStartProviders(); bool DoStartProviders();
// Gets called when a provider has a new position. // Gets called when a provider has a new position.
void OnLocationUpdate(const LocationProvider* provider, void OnLocationUpdate(const LocationProvider* provider,
...@@ -97,8 +97,7 @@ class DEVICE_GEOLOCATION_EXPORT LocationArbitratorImpl ...@@ -97,8 +97,7 @@ class DEVICE_GEOLOCATION_EXPORT LocationArbitratorImpl
GeolocationDelegate* delegate_; GeolocationDelegate* delegate_;
scoped_refptr<AccessTokenStore> access_token_store_; scoped_refptr<AccessTokenStore> access_token_store_;
LocationUpdateCallback arbitrator_update_callback_; LocationProvider::LocationProviderUpdateCallback arbitrator_update_callback_;
LocationProvider::LocationProviderUpdateCallback provider_update_callback_;
// The CancelableCallback will prevent OnAccessTokenStoresLoaded from being // The CancelableCallback will prevent OnAccessTokenStoresLoaded from being
// called multiple times by calling Reset() at the time of binding. // called multiple times by calling Reset() at the time of binding.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "device/geolocation/location_arbitrator_impl.h" #include "device/geolocation/location_arbitrator_impl.h"
#include <memory> #include <memory>
#include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
...@@ -29,7 +30,7 @@ class MockLocationObserver { ...@@ -29,7 +30,7 @@ class MockLocationObserver {
ASSERT_FALSE(last_position_.Validate()); ASSERT_FALSE(last_position_.Validate());
} }
// Delegate // Delegate
void OnLocationUpdate(const Geoposition& position) { void OnLocationUpdate(const LocationProvider*, const Geoposition& position) {
last_position_ = position; last_position_ = position;
} }
...@@ -95,13 +96,15 @@ class FakeGeolocationDelegate : public GeolocationDelegate { ...@@ -95,13 +96,15 @@ class FakeGeolocationDelegate : public GeolocationDelegate {
class TestingLocationArbitrator : public LocationArbitratorImpl { class TestingLocationArbitrator : public LocationArbitratorImpl {
public: public:
TestingLocationArbitrator( TestingLocationArbitrator(
const LocationArbitratorImpl::LocationUpdateCallback& callback, const LocationProviderUpdateCallback& callback,
const scoped_refptr<AccessTokenStore>& access_token_store, const scoped_refptr<AccessTokenStore>& access_token_store,
GeolocationDelegate* delegate) GeolocationDelegate* delegate)
: LocationArbitratorImpl(callback, delegate), : LocationArbitratorImpl(delegate),
cell_(nullptr), cell_(nullptr),
gps_(nullptr), gps_(nullptr),
access_token_store_(access_token_store) {} access_token_store_(access_token_store) {
SetUpdateCallback(callback);
}
base::Time GetTimeNow() const override { return GetTimeNowForTest(); } base::Time GetTimeNow() const override { return GetTimeNowForTest(); }
...@@ -146,7 +149,7 @@ class GeolocationLocationArbitratorTest : public testing::Test { ...@@ -146,7 +149,7 @@ class GeolocationLocationArbitratorTest : public testing::Test {
void InitializeArbitrator(std::unique_ptr<GeolocationDelegate> delegate) { void InitializeArbitrator(std::unique_ptr<GeolocationDelegate> delegate) {
if (delegate) if (delegate)
delegate_ = std::move(delegate); delegate_ = std::move(delegate);
const LocationArbitratorImpl::LocationUpdateCallback callback = const LocationProvider::LocationProviderUpdateCallback callback =
base::Bind(&MockLocationObserver::OnLocationUpdate, base::Bind(&MockLocationObserver::OnLocationUpdate,
base::Unretained(observer_.get())); base::Unretained(observer_.get()));
arbitrator_.reset(new TestingLocationArbitrator( arbitrator_.reset(new TestingLocationArbitrator(
...@@ -193,9 +196,9 @@ TEST_F(GeolocationLocationArbitratorTest, CreateDestroy) { ...@@ -193,9 +196,9 @@ TEST_F(GeolocationLocationArbitratorTest, CreateDestroy) {
TEST_F(GeolocationLocationArbitratorTest, OnPermissionGranted) { TEST_F(GeolocationLocationArbitratorTest, OnPermissionGranted) {
InitializeArbitrator(nullptr); InitializeArbitrator(nullptr);
EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted()); EXPECT_FALSE(arbitrator_->HasPermissionBeenGrantedForTest());
arbitrator_->OnPermissionGranted(); arbitrator_->OnPermissionGranted();
EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted()); EXPECT_TRUE(arbitrator_->HasPermissionBeenGrantedForTest());
// Can't check the provider has been notified without going through the // Can't check the provider has been notified without going through the
// motions to create the provider (see next test). // motions to create the provider (see next test).
EXPECT_FALSE(cell()); EXPECT_FALSE(cell());
...@@ -209,7 +212,7 @@ TEST_F(GeolocationLocationArbitratorTest, NormalUsage) { ...@@ -209,7 +212,7 @@ TEST_F(GeolocationLocationArbitratorTest, NormalUsage) {
EXPECT_FALSE(cell()); EXPECT_FALSE(cell());
EXPECT_FALSE(gps()); EXPECT_FALSE(gps());
arbitrator_->StartProviders(false); arbitrator_->StartProvider(false);
EXPECT_TRUE(access_token_store_->access_token_map_.empty()); EXPECT_TRUE(access_token_store_->access_token_map_.empty());
...@@ -226,13 +229,13 @@ TEST_F(GeolocationLocationArbitratorTest, NormalUsage) { ...@@ -226,13 +229,13 @@ TEST_F(GeolocationLocationArbitratorTest, NormalUsage) {
EXPECT_TRUE(observer_->last_position_.Validate() || EXPECT_TRUE(observer_->last_position_.Validate() ||
observer_->last_position_.error_code != observer_->last_position_.error_code !=
Geoposition::ERROR_CODE_NONE); Geoposition::ERROR_CODE_NONE);
EXPECT_EQ(cell()->position_.latitude, observer_->last_position_.latitude); EXPECT_EQ(cell()->position().latitude, observer_->last_position_.latitude);
EXPECT_FALSE(cell()->is_permission_granted_); EXPECT_FALSE(cell()->is_permission_granted());
EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted()); EXPECT_FALSE(arbitrator_->HasPermissionBeenGrantedForTest());
arbitrator_->OnPermissionGranted(); arbitrator_->OnPermissionGranted();
EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted()); EXPECT_TRUE(arbitrator_->HasPermissionBeenGrantedForTest());
EXPECT_TRUE(cell()->is_permission_granted_); EXPECT_TRUE(cell()->is_permission_granted());
} }
TEST_F(GeolocationLocationArbitratorTest, CustomSystemProviderOnly) { TEST_F(GeolocationLocationArbitratorTest, CustomSystemProviderOnly) {
...@@ -245,7 +248,7 @@ TEST_F(GeolocationLocationArbitratorTest, CustomSystemProviderOnly) { ...@@ -245,7 +248,7 @@ TEST_F(GeolocationLocationArbitratorTest, CustomSystemProviderOnly) {
EXPECT_FALSE(cell()); EXPECT_FALSE(cell());
EXPECT_FALSE(gps()); EXPECT_FALSE(gps());
arbitrator_->StartProviders(false); arbitrator_->StartProvider(false);
ASSERT_FALSE(cell()); ASSERT_FALSE(cell());
EXPECT_FALSE(gps()); EXPECT_FALSE(gps());
...@@ -260,14 +263,15 @@ TEST_F(GeolocationLocationArbitratorTest, CustomSystemProviderOnly) { ...@@ -260,14 +263,15 @@ TEST_F(GeolocationLocationArbitratorTest, CustomSystemProviderOnly) {
EXPECT_TRUE(observer_->last_position_.Validate() || EXPECT_TRUE(observer_->last_position_.Validate() ||
observer_->last_position_.error_code != observer_->last_position_.error_code !=
Geoposition::ERROR_CODE_NONE); Geoposition::ERROR_CODE_NONE);
EXPECT_EQ(fake_delegate->mock_location_provider()->position_.latitude, EXPECT_EQ(fake_delegate->mock_location_provider()->position().latitude,
observer_->last_position_.latitude); observer_->last_position_.latitude);
EXPECT_FALSE(fake_delegate->mock_location_provider()->is_permission_granted_); EXPECT_FALSE(
EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted()); fake_delegate->mock_location_provider()->is_permission_granted());
EXPECT_FALSE(arbitrator_->HasPermissionBeenGrantedForTest());
arbitrator_->OnPermissionGranted(); arbitrator_->OnPermissionGranted();
EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted()); EXPECT_TRUE(arbitrator_->HasPermissionBeenGrantedForTest());
EXPECT_TRUE(fake_delegate->mock_location_provider()->is_permission_granted_); EXPECT_TRUE(fake_delegate->mock_location_provider()->is_permission_granted());
} }
TEST_F(GeolocationLocationArbitratorTest, TEST_F(GeolocationLocationArbitratorTest,
...@@ -281,7 +285,7 @@ TEST_F(GeolocationLocationArbitratorTest, ...@@ -281,7 +285,7 @@ TEST_F(GeolocationLocationArbitratorTest,
EXPECT_FALSE(cell()); EXPECT_FALSE(cell());
EXPECT_FALSE(gps()); EXPECT_FALSE(gps());
arbitrator_->StartProviders(false); arbitrator_->StartProvider(false);
EXPECT_TRUE(access_token_store_->access_token_map_.empty()); EXPECT_TRUE(access_token_store_->access_token_map_.empty());
...@@ -301,18 +305,18 @@ TEST_F(GeolocationLocationArbitratorTest, ...@@ -301,18 +305,18 @@ TEST_F(GeolocationLocationArbitratorTest,
EXPECT_TRUE(observer_->last_position_.Validate() || EXPECT_TRUE(observer_->last_position_.Validate() ||
observer_->last_position_.error_code != observer_->last_position_.error_code !=
Geoposition::ERROR_CODE_NONE); Geoposition::ERROR_CODE_NONE);
EXPECT_EQ(cell()->position_.latitude, observer_->last_position_.latitude); EXPECT_EQ(cell()->position().latitude, observer_->last_position_.latitude);
EXPECT_FALSE(cell()->is_permission_granted_); EXPECT_FALSE(cell()->is_permission_granted());
EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted()); EXPECT_FALSE(arbitrator_->HasPermissionBeenGrantedForTest());
arbitrator_->OnPermissionGranted(); arbitrator_->OnPermissionGranted();
EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted()); EXPECT_TRUE(arbitrator_->HasPermissionBeenGrantedForTest());
EXPECT_TRUE(cell()->is_permission_granted_); EXPECT_TRUE(cell()->is_permission_granted());
} }
TEST_F(GeolocationLocationArbitratorTest, SetObserverOptions) { TEST_F(GeolocationLocationArbitratorTest, SetObserverOptions) {
InitializeArbitrator(nullptr); InitializeArbitrator(nullptr);
arbitrator_->StartProviders(false); arbitrator_->StartProvider(false);
access_token_store_->NotifyDelegateTokensLoaded(); access_token_store_->NotifyDelegateTokensLoaded();
ASSERT_TRUE(cell()); ASSERT_TRUE(cell());
ASSERT_TRUE(gps()); ASSERT_TRUE(gps());
...@@ -321,14 +325,14 @@ TEST_F(GeolocationLocationArbitratorTest, SetObserverOptions) { ...@@ -321,14 +325,14 @@ TEST_F(GeolocationLocationArbitratorTest, SetObserverOptions) {
SetReferencePosition(cell()); SetReferencePosition(cell());
EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_); EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_);
EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_); EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_);
arbitrator_->StartProviders(true); arbitrator_->StartProvider(true);
EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, cell()->state_); EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, cell()->state_);
EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, gps()->state_); EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, gps()->state_);
} }
TEST_F(GeolocationLocationArbitratorTest, Arbitration) { TEST_F(GeolocationLocationArbitratorTest, Arbitration) {
InitializeArbitrator(nullptr); InitializeArbitrator(nullptr);
arbitrator_->StartProviders(false); arbitrator_->StartProvider(false);
access_token_store_->NotifyDelegateTokensLoaded(); access_token_store_->NotifyDelegateTokensLoaded();
ASSERT_TRUE(cell()); ASSERT_TRUE(cell());
ASSERT_TRUE(gps()); ASSERT_TRUE(gps());
...@@ -351,7 +355,7 @@ TEST_F(GeolocationLocationArbitratorTest, Arbitration) { ...@@ -351,7 +355,7 @@ TEST_F(GeolocationLocationArbitratorTest, Arbitration) {
// Advance time, and notify once again // Advance time, and notify once again
AdvanceTimeNow(SwitchOnFreshnessCliff()); AdvanceTimeNow(SwitchOnFreshnessCliff());
cell()->HandlePositionChanged(cell()->position_); cell()->HandlePositionChanged(cell()->position());
// New fix is available, less accurate but fresher // New fix is available, less accurate but fresher
CheckLastPositionInfo(5, 6, 150); CheckLastPositionInfo(5, 6, 150);
...@@ -405,7 +409,7 @@ TEST_F(GeolocationLocationArbitratorTest, Arbitration) { ...@@ -405,7 +409,7 @@ TEST_F(GeolocationLocationArbitratorTest, Arbitration) {
TEST_F(GeolocationLocationArbitratorTest, TwoOneShotsIsNewPositionBetter) { TEST_F(GeolocationLocationArbitratorTest, TwoOneShotsIsNewPositionBetter) {
InitializeArbitrator(nullptr); InitializeArbitrator(nullptr);
arbitrator_->StartProviders(false); arbitrator_->StartProvider(false);
access_token_store_->NotifyDelegateTokensLoaded(); access_token_store_->NotifyDelegateTokensLoaded();
ASSERT_TRUE(cell()); ASSERT_TRUE(cell());
ASSERT_TRUE(gps()); ASSERT_TRUE(gps());
...@@ -415,14 +419,14 @@ TEST_F(GeolocationLocationArbitratorTest, TwoOneShotsIsNewPositionBetter) { ...@@ -415,14 +419,14 @@ TEST_F(GeolocationLocationArbitratorTest, TwoOneShotsIsNewPositionBetter) {
CheckLastPositionInfo(3, 139, 100); CheckLastPositionInfo(3, 139, 100);
// Restart providers to simulate a one-shot request. // Restart providers to simulate a one-shot request.
arbitrator_->StopProviders(); arbitrator_->StopProvider();
// To test 240956, perform a throwaway alloc. // To test 240956, perform a throwaway alloc.
// This convinces the allocator to put the providers in a new memory location. // This convinces the allocator to put the providers in a new memory location.
std::unique_ptr<MockLocationProvider> dummy_provider( std::unique_ptr<MockLocationProvider> dummy_provider(
new MockLocationProvider); new MockLocationProvider);
arbitrator_->StartProviders(false); arbitrator_->StartProvider(false);
access_token_store_->NotifyDelegateTokensLoaded(); access_token_store_->NotifyDelegateTokensLoaded();
// Advance the time a short while to simulate successive calls. // Advance the time a short while to simulate successive calls.
......
...@@ -14,7 +14,7 @@ namespace device { ...@@ -14,7 +14,7 @@ namespace device {
class LocationProvider; class LocationProvider;
// The interface for providing location information. // The interface for providing location information.
class LocationProvider { class DEVICE_GEOLOCATION_EXPORT LocationProvider {
public: public:
virtual ~LocationProvider() {} virtual ~LocationProvider() {}
...@@ -40,11 +40,7 @@ class LocationProvider { ...@@ -40,11 +40,7 @@ class LocationProvider {
virtual void StopProvider() = 0; virtual void StopProvider() = 0;
// Gets the current best position estimate. // Gets the current best position estimate.
virtual void GetPosition(Geoposition* position) = 0; virtual const Geoposition& GetPosition() = 0;
// Provides a hint to the provider that new location data is needed as soon
// as possible.
virtual void RequestRefresh() = 0;
// Called everytime permission is granted to a page for using geolocation. // Called everytime permission is granted to a page for using geolocation.
// This may either be through explicit user action (e.g. responding to the // This may either be through explicit user action (e.g. responding to the
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "device/geolocation/location_provider_android.h" #include "device/geolocation/location_provider_android.h"
#include <memory>
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "device/geolocation/geoposition.h" #include "device/geolocation/geoposition.h"
...@@ -32,12 +34,8 @@ void LocationProviderAndroid::StopProvider() { ...@@ -32,12 +34,8 @@ void LocationProviderAndroid::StopProvider() {
AndroidLocationApiAdapter::GetInstance()->Stop(); AndroidLocationApiAdapter::GetInstance()->Stop();
} }
void LocationProviderAndroid::GetPosition(Geoposition* position) { const Geoposition& LocationProviderAndroid::GetPosition() {
*position = last_position_; return last_position_;
}
void LocationProviderAndroid::RequestRefresh() {
// Nothing to do here, android framework will call us back on new position.
} }
void LocationProviderAndroid::OnPermissionGranted() { void LocationProviderAndroid::OnPermissionGranted() {
......
...@@ -25,8 +25,7 @@ class LocationProviderAndroid : public LocationProviderBase { ...@@ -25,8 +25,7 @@ class LocationProviderAndroid : public LocationProviderBase {
// LocationProvider. // LocationProvider.
bool StartProvider(bool high_accuracy) override; bool StartProvider(bool high_accuracy) override;
void StopProvider() override; void StopProvider() override;
void GetPosition(Geoposition* position) override; const Geoposition& GetPosition() override;
void RequestRefresh() override;
void OnPermissionGranted() override; void OnPermissionGranted() override;
private: private:
......
...@@ -20,6 +20,4 @@ void LocationProviderBase::SetUpdateCallback( ...@@ -20,6 +20,4 @@ void LocationProviderBase::SetUpdateCallback(
callback_ = callback; callback_ = callback;
} }
void LocationProviderBase::RequestRefresh() {}
} // namespace device } // namespace device
...@@ -23,7 +23,6 @@ class DEVICE_GEOLOCATION_EXPORT LocationProviderBase ...@@ -23,7 +23,6 @@ class DEVICE_GEOLOCATION_EXPORT LocationProviderBase
// Overridden from LocationProvider: // Overridden from LocationProvider:
void SetUpdateCallback( void SetUpdateCallback(
const LocationProviderUpdateCallback& callback) override; const LocationProviderUpdateCallback& callback) override;
void RequestRefresh() override;
private: private:
LocationProviderUpdateCallback callback_; LocationProviderUpdateCallback callback_;
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "device/geolocation/mock_location_arbitrator.h"
#include "base/message_loop/message_loop.h"
#include "device/geolocation/geoposition.h"
namespace device {
MockLocationArbitrator::MockLocationArbitrator()
: permission_granted_(false), providers_started_(false) {}
void MockLocationArbitrator::StartProviders(bool enable_high_accuracy) {
providers_started_ = true;
}
void MockLocationArbitrator::StopProviders() {
providers_started_ = false;
}
void MockLocationArbitrator::OnPermissionGranted() {
permission_granted_ = true;
}
bool MockLocationArbitrator::HasPermissionBeenGranted() const {
return permission_granted_;
}
} // namespace device
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_GEOLOCATION_MOCK_LOCATION_ARBITRATOR_H_
#define DEVICE_GEOLOCATION_MOCK_LOCATION_ARBITRATOR_H_
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "device/geolocation/location_arbitrator.h"
namespace device {
struct Geoposition;
class MockLocationArbitrator : public LocationArbitrator {
public:
MockLocationArbitrator();
bool providers_started() const { return providers_started_; }
// LocationArbitrator:
void StartProviders(bool enable_high_accuracy) override;
void StopProviders() override;
void OnPermissionGranted() override;
bool HasPermissionBeenGranted() const override;
private:
bool permission_granted_;
bool providers_started_;
DISALLOW_COPY_AND_ASSIGN(MockLocationArbitrator);
};
} // namespace device
#endif // DEVICE_GEOLOCATION_MOCK_LOCATION_ARBITRATOR_H_
...@@ -46,79 +46,12 @@ void MockLocationProvider::StopProvider() { ...@@ -46,79 +46,12 @@ void MockLocationProvider::StopProvider() {
state_ = STOPPED; state_ = STOPPED;
} }
void MockLocationProvider::GetPosition(Geoposition* position) { const Geoposition& MockLocationProvider::GetPosition() {
*position = position_; return position_;
} }
void MockLocationProvider::OnPermissionGranted() { void MockLocationProvider::OnPermissionGranted() {
is_permission_granted_ = true; is_permission_granted_ = true;
} }
// Mock location provider that automatically calls back its client at most
// once, when StartProvider or OnPermissionGranted is called. Use
// |requires_permission_to_start| to select which event triggers the callback.
class AutoMockLocationProvider : public MockLocationProvider {
public:
AutoMockLocationProvider(bool has_valid_location,
bool requires_permission_to_start)
: requires_permission_to_start_(requires_permission_to_start),
listeners_updated_(false) {
if (has_valid_location) {
position_.accuracy = 3;
position_.latitude = 4.3;
position_.longitude = -7.8;
// Webkit compares the timestamp to wall clock time, so we need it to be
// contemporary.
position_.timestamp = base::Time::Now();
} else {
position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
}
}
bool StartProvider(bool high_accuracy) override {
MockLocationProvider::StartProvider(high_accuracy);
if (!requires_permission_to_start_) {
UpdateListenersIfNeeded();
}
return true;
}
void OnPermissionGranted() override {
MockLocationProvider::OnPermissionGranted();
if (requires_permission_to_start_) {
UpdateListenersIfNeeded();
}
}
void UpdateListenersIfNeeded() {
if (!listeners_updated_) {
listeners_updated_ = true;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&MockLocationProvider::HandlePositionChanged,
base::Unretained(this), position_));
}
}
private:
const bool requires_permission_to_start_;
bool listeners_updated_;
DISALLOW_COPY_AND_ASSIGN(AutoMockLocationProvider);
};
LocationProvider* NewMockLocationProvider() {
return new MockLocationProvider;
}
LocationProvider* NewAutoSuccessMockLocationProvider() {
return new AutoMockLocationProvider(true, false);
}
LocationProvider* NewAutoFailMockLocationProvider() {
return new AutoMockLocationProvider(false, false);
}
LocationProvider* NewAutoSuccessMockNetworkLocationProvider() {
return new AutoMockLocationProvider(true, true);
}
} // namespace device } // namespace device
...@@ -23,41 +23,27 @@ class MockLocationProvider : public LocationProviderBase { ...@@ -23,41 +23,27 @@ class MockLocationProvider : public LocationProviderBase {
MockLocationProvider(); MockLocationProvider();
~MockLocationProvider() override; ~MockLocationProvider() override;
bool is_started() const { return state_ != STOPPED; }
bool is_permission_granted() const { return is_permission_granted_; }
const Geoposition& position() const { return position_; }
// Updates listeners with the new position. // Updates listeners with the new position.
void HandlePositionChanged(const Geoposition& position); void HandlePositionChanged(const Geoposition& position);
// LocationProvider implementation. // LocationProvider implementation.
bool StartProvider(bool high_accuracy) override; bool StartProvider(bool high_accuracy) override;
void StopProvider() override; void StopProvider() override;
void GetPosition(Geoposition* position) override; const Geoposition& GetPosition() override;
void OnPermissionGranted() override; void OnPermissionGranted() override;
private:
bool is_permission_granted_; bool is_permission_granted_;
Geoposition position_; Geoposition position_;
scoped_refptr<base::SingleThreadTaskRunner> provider_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> provider_task_runner_;
private:
DISALLOW_COPY_AND_ASSIGN(MockLocationProvider); DISALLOW_COPY_AND_ASSIGN(MockLocationProvider);
}; };
// Factory functions for the various sorts of mock location providers,
// for use with LocationArbitrator::SetProviderFactoryForTest (i.e.
// not intended for test code to use to get access to the mock, you can use
// MockLocationProvider::instance_ for this, or make a custom factory method).
// Creates a mock location provider with no default behavior.
LocationProvider* NewMockLocationProvider();
// Creates a mock location provider that automatically notifies its
// listeners with a valid location when StartProvider is called.
LocationProvider* NewAutoSuccessMockLocationProvider();
// Creates a mock location provider that automatically notifies its
// listeners with an error when StartProvider is called.
LocationProvider* NewAutoFailMockLocationProvider();
// Similar to NewAutoSuccessMockLocationProvider but mimicks the behavior of
// the Network Location provider, in deferring making location updates until
// a permission request has been confirmed.
LocationProvider* NewAutoSuccessMockNetworkLocationProvider();
} // namespace device } // namespace device
#endif // DEVICE_GEOLOCATION_MOCK_LOCATION_PROVIDER_H_ #endif // DEVICE_GEOLOCATION_MOCK_LOCATION_PROVIDER_H_
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "device/geolocation/network_location_provider.h" #include "device/geolocation/network_location_provider.h"
#include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/location.h" #include "base/location.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
...@@ -128,26 +130,15 @@ NetworkLocationProvider::~NetworkLocationProvider() { ...@@ -128,26 +130,15 @@ NetworkLocationProvider::~NetworkLocationProvider() {
} }
// LocationProvider implementation // LocationProvider implementation
void NetworkLocationProvider::GetPosition(Geoposition* position) { const Geoposition& NetworkLocationProvider::GetPosition() {
DCHECK(position); return position_;
*position = position_;
}
void NetworkLocationProvider::RequestRefresh() {
// TODO(joth): When called via the public (base class) interface, this should
// poke each data provider to get them to expedite their next scan.
// Whilst in the delayed start, only send request if all data is ready.
// TODO(mcasas): consider not using HasWeakPtrs() https://crbug.com/629158.
if (!weak_factory_.HasWeakPtrs() || is_wifi_data_complete_) {
RequestPosition();
}
} }
void NetworkLocationProvider::OnPermissionGranted() { void NetworkLocationProvider::OnPermissionGranted() {
const bool was_permission_granted = is_permission_granted_; const bool was_permission_granted = is_permission_granted_;
is_permission_granted_ = true; is_permission_granted_ = true;
if (!was_permission_granted && IsStarted()) { if (!was_permission_granted && IsStarted()) {
RequestRefresh(); RequestPosition();
} }
} }
...@@ -212,7 +203,7 @@ void NetworkLocationProvider::OnWifiDataUpdated() { ...@@ -212,7 +203,7 @@ void NetworkLocationProvider::OnWifiDataUpdated() {
wifi_timestamp_ = base::Time::Now(); wifi_timestamp_ = base::Time::Now();
is_new_data_available_ = is_wifi_data_complete_; is_new_data_available_ = is_wifi_data_complete_;
RequestRefresh(); RequestPosition();
} }
void NetworkLocationProvider::StopProvider() { void NetworkLocationProvider::StopProvider() {
...@@ -227,6 +218,10 @@ void NetworkLocationProvider::StopProvider() { ...@@ -227,6 +218,10 @@ void NetworkLocationProvider::StopProvider() {
// Other methods // Other methods
void NetworkLocationProvider::RequestPosition() { void NetworkLocationProvider::RequestPosition() {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
// TODO(mcasas): consider not using HasWeakPtrs() https://crbug.com/629158.
if (weak_factory_.HasWeakPtrs() && !is_wifi_data_complete_)
return;
if (!is_new_data_available_) if (!is_new_data_available_)
return; return;
...@@ -238,11 +233,13 @@ void NetworkLocationProvider::RequestPosition() { ...@@ -238,11 +233,13 @@ void NetworkLocationProvider::RequestPosition() {
DCHECK(cached_position->Validate()); DCHECK(cached_position->Validate());
// Record the position and update its timestamp. // Record the position and update its timestamp.
position_ = *cached_position; position_ = *cached_position;
// The timestamp of a position fix is determined by the timestamp // The timestamp of a position fix is determined by the timestamp
// of the source data update. (The value of position_.timestamp from // of the source data update. (The value of position_.timestamp from
// the cache could be from weeks ago!) // the cache could be from weeks ago!)
position_.timestamp = wifi_timestamp_; position_.timestamp = wifi_timestamp_;
is_new_data_available_ = false; is_new_data_available_ = false;
// Let listeners know that we now have a position available. // Let listeners know that we now have a position available.
NotifyCallback(position_); NotifyCallback(position_);
return; return;
......
...@@ -73,8 +73,7 @@ class NetworkLocationProvider : public base::NonThreadSafe, ...@@ -73,8 +73,7 @@ class NetworkLocationProvider : public base::NonThreadSafe,
// LocationProvider implementation // LocationProvider implementation
bool StartProvider(bool high_accuracy) override; bool StartProvider(bool high_accuracy) override;
void StopProvider() override; void StopProvider() override;
void GetPosition(Geoposition* position) override; const Geoposition& GetPosition() override;
void RequestRefresh() override;
void OnPermissionGranted() override; void OnPermissionGranted() override;
private: private:
......
...@@ -7,7 +7,9 @@ ...@@ -7,7 +7,9 @@
#include <stddef.h> #include <stddef.h>
#include <memory> #include <memory>
#include <string>
#include <utility> #include <utility>
#include <vector>
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
...@@ -277,9 +279,9 @@ class GeolocationNetworkProviderTest : public testing::Test { ...@@ -277,9 +279,9 @@ class GeolocationNetworkProviderTest : public testing::Test {
ASSERT_TRUE(parsed_json->GetAsDictionary(&request_json)); ASSERT_TRUE(parsed_json->GetAsDictionary(&request_json));
if (!is_default_url) { if (!is_default_url) {
if (expected_access_token.empty()) if (expected_access_token.empty()) {
ASSERT_FALSE(request_json->HasKey(kAccessTokenString)); ASSERT_FALSE(request_json->HasKey(kAccessTokenString));
else { } else {
std::string access_token; std::string access_token;
EXPECT_TRUE(request_json->GetString(kAccessTokenString, &access_token)); EXPECT_TRUE(request_json->GetString(kAccessTokenString, &access_token));
EXPECT_EQ(expected_access_token, access_token); EXPECT_EQ(expected_access_token, access_token);
...@@ -381,8 +383,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) { ...@@ -381,8 +383,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) {
fetcher->SetResponseString(kNoFixNetworkResponse); fetcher->SetResponseString(kNoFixNetworkResponse);
fetcher->delegate()->OnURLFetchComplete(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher);
Geoposition position; Geoposition position = provider->GetPosition();
provider->GetPosition(&position);
EXPECT_FALSE(position.Validate()); EXPECT_FALSE(position.Validate());
// Now wifi data arrives -- SetData will notify listeners. // Now wifi data arrives -- SetData will notify listeners.
...@@ -411,7 +412,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) { ...@@ -411,7 +412,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) {
fetcher->SetResponseString(kReferenceNetworkResponse); fetcher->SetResponseString(kReferenceNetworkResponse);
fetcher->delegate()->OnURLFetchComplete(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher);
provider->GetPosition(&position); position = provider->GetPosition();
EXPECT_EQ(51.0, position.latitude); EXPECT_EQ(51.0, position.latitude);
EXPECT_EQ(-0.1, position.longitude); EXPECT_EQ(-0.1, position.longitude);
EXPECT_EQ(1200.4, position.accuracy); EXPECT_EQ(1200.4, position.accuracy);
...@@ -430,7 +431,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) { ...@@ -430,7 +431,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) {
fetcher = get_url_fetcher_and_advance_id(); fetcher = get_url_fetcher_and_advance_id();
EXPECT_FALSE(fetcher); EXPECT_FALSE(fetcher);
provider->GetPosition(&position); position = provider->GetPosition();
EXPECT_EQ(51.0, position.latitude); EXPECT_EQ(51.0, position.latitude);
EXPECT_EQ(-0.1, position.longitude); EXPECT_EQ(-0.1, position.longitude);
EXPECT_TRUE(position.Validate()); EXPECT_TRUE(position.Validate());
...@@ -451,7 +452,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) { ...@@ -451,7 +452,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) {
fetcher->delegate()->OnURLFetchComplete(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher);
// Error means we now no longer have a fix. // Error means we now no longer have a fix.
provider->GetPosition(&position); position = provider->GetPosition();
EXPECT_FALSE(position.Validate()); EXPECT_FALSE(position.Validate());
// Wifi scan returns to original set: should be serviced from cache. // Wifi scan returns to original set: should be serviced from cache.
...@@ -459,7 +460,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) { ...@@ -459,7 +460,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_FALSE(get_url_fetcher_and_advance_id()); // No new request created. EXPECT_FALSE(get_url_fetcher_and_advance_id()); // No new request created.
provider->GetPosition(&position); position = provider->GetPosition();
EXPECT_EQ(51.0, position.latitude); EXPECT_EQ(51.0, position.latitude);
EXPECT_EQ(-0.1, position.longitude); EXPECT_EQ(-0.1, position.longitude);
EXPECT_TRUE(position.Validate()); EXPECT_TRUE(position.Validate());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment