diff options
author | jknotten@chromium.org <jknotten@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-30 13:00:40 +0000 |
---|---|---|
committer | jknotten@chromium.org <jknotten@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-30 13:00:40 +0000 |
commit | 90984b00d84729a170cdb6a2b863e47b15ff7aea (patch) | |
tree | 0969d0390030262306593d5905e40e95c44ce831 /content/browser/geolocation/location_arbitrator_impl.cc | |
parent | bade57cab535b5459975b44ea4e85362c576deea (diff) | |
download | chromium_src-90984b00d84729a170cdb6a2b863e47b15ff7aea.zip chromium_src-90984b00d84729a170cdb6a2b863e47b15ff7aea.tar.gz chromium_src-90984b00d84729a170cdb6a2b863e47b15ff7aea.tar.bz2 |
Cleanup: use MockGeolocationArbitrator to test GeolocationProvider
This patch introduces a MockGeolocationArbitrator class for use
with the GeolocationProvider unittests. This avoids having to
instantiate dependencies of the GeolocationArbitrator to test the
GeolocationProvider.
This will make it easier to add a unit test for
https://codereview.chromium.org/11312210/
TEST=Existing
BUG=
Review URL: https://chromiumcodereview.appspot.com/11412194
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@170444 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/geolocation/location_arbitrator_impl.cc')
-rw-r--r-- | content/browser/geolocation/location_arbitrator_impl.cc | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/content/browser/geolocation/location_arbitrator_impl.cc b/content/browser/geolocation/location_arbitrator_impl.cc new file mode 100644 index 0000000..97cae8e --- /dev/null +++ b/content/browser/geolocation/location_arbitrator_impl.cc @@ -0,0 +1,185 @@ +// 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 "content/browser/geolocation/location_arbitrator_impl.h" + +#include <map> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "content/public/browser/access_token_store.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/common/content_client.h" +#include "googleurl/src/gurl.h" + +namespace content { +namespace { + +const char* kDefaultNetworkProviderUrl = + "https://www.googleapis.com/geolocation/v1/geolocate"; +} // namespace + +// To avoid oscillations, set this to twice the expected update interval of a +// a GPS-type location provider (in case it misses a beat) plus a little. +const int64 GeolocationArbitratorImpl::kFixStaleTimeoutMilliseconds = + 11 * base::Time::kMillisecondsPerSecond; + +GeolocationArbitratorImpl::GeolocationArbitratorImpl( + GeolocationObserver* observer) + : observer_(observer), + position_provider_(NULL), + is_permission_granted_(false) { +} + +GeolocationArbitratorImpl::~GeolocationArbitratorImpl() { +} + +GURL GeolocationArbitratorImpl::DefaultNetworkProviderURL() { + return GURL(kDefaultNetworkProviderUrl); +} + +void GeolocationArbitratorImpl::OnPermissionGranted() { + is_permission_granted_ = true; + for (ScopedVector<LocationProviderBase>::iterator i = providers_.begin(); + i != providers_.end(); ++i) { + (*i)->OnPermissionGranted(); + } +} + +void GeolocationArbitratorImpl::StartProviders( + const GeolocationObserverOptions& options) { + // Stash options as OnAccessTokenStoresLoaded has not yet been called. + current_provider_options_ = options; + if (providers_.empty()) { + DCHECK(DefaultNetworkProviderURL().is_valid()); + GetAccessTokenStore()->LoadAccessTokens( + base::Bind(&GeolocationArbitratorImpl::OnAccessTokenStoresLoaded, + base::Unretained(this))); + } else { + DoStartProviders(); + } +} + +void GeolocationArbitratorImpl::DoStartProviders() { + for (ScopedVector<LocationProviderBase>::iterator i = providers_.begin(); + i != providers_.end(); ++i) { + (*i)->StartProvider(current_provider_options_.use_high_accuracy); + } +} + +void GeolocationArbitratorImpl::StopProviders() { + providers_.clear(); +} + +void GeolocationArbitratorImpl::OnAccessTokenStoresLoaded( + AccessTokenStore::AccessTokenSet access_token_set, + net::URLRequestContextGetter* context_getter) { + if (!providers_.empty()) { + // A second StartProviders() call may have arrived before the first + // completed. + return; + } + // If there are no access tokens, boot strap it with the default server URL. + if (access_token_set.empty()) + access_token_set[DefaultNetworkProviderURL()]; + for (AccessTokenStore::AccessTokenSet::iterator i = + access_token_set.begin(); + i != access_token_set.end(); ++i) { + RegisterProvider( + NewNetworkLocationProvider( + GetAccessTokenStore(), context_getter, + i->first, i->second)); + } + RegisterProvider(NewSystemLocationProvider()); + DoStartProviders(); +} + +void GeolocationArbitratorImpl::RegisterProvider( + LocationProviderBase* provider) { + if (!provider) + return; + provider->RegisterListener(this); + if (is_permission_granted_) + provider->OnPermissionGranted(); + providers_.push_back(provider); +} + +void GeolocationArbitratorImpl::LocationUpdateAvailable( + LocationProviderBase* provider) { + DCHECK(provider); + Geoposition new_position; + provider->GetPosition(&new_position); + DCHECK(new_position.Validate() || + new_position.error_code != Geoposition::ERROR_CODE_NONE); + if (!IsNewPositionBetter(position_, new_position, + provider == position_provider_)) + return; + position_provider_ = provider; + position_ = new_position; + observer_->OnLocationUpdate(position_); +} + +AccessTokenStore* GeolocationArbitratorImpl::NewAccessTokenStore() { + return GetContentClient()->browser()->CreateAccessTokenStore(); +} + +AccessTokenStore* GeolocationArbitratorImpl::GetAccessTokenStore() { + if (!access_token_store_.get()) + access_token_store_ = NewAccessTokenStore(); + return access_token_store_.get(); +} + +LocationProviderBase* GeolocationArbitratorImpl::NewNetworkLocationProvider( + AccessTokenStore* access_token_store, + net::URLRequestContextGetter* context, + const GURL& url, + const string16& access_token) { +#if defined(OS_ANDROID) + // Android uses its own SystemLocationProvider. + return NULL; +#else + return content::NewNetworkLocationProvider(access_token_store, context, url, + access_token); +#endif +} + +LocationProviderBase* GeolocationArbitratorImpl::NewSystemLocationProvider() { + return content::NewSystemLocationProvider(); +} + +base::Time GeolocationArbitratorImpl::GetTimeNow() const { + return base::Time::Now(); +} + +bool GeolocationArbitratorImpl::IsNewPositionBetter( + const Geoposition& old_position, const Geoposition& new_position, + bool from_same_provider) const { + // Updates location_info if it's better than what we currently have, + // or if it's a newer update from the same provider. + if (!old_position.Validate()) { + // Older location wasn't locked. + return true; + } + if (new_position.Validate()) { + // New location is locked, let's check if it's any better. + if (old_position.accuracy >= new_position.accuracy) { + // Accuracy is better. + return true; + } else if (from_same_provider) { + // Same provider, fresher location. + return true; + } else if ((GetTimeNow() - old_position.timestamp).InMilliseconds() > + kFixStaleTimeoutMilliseconds) { + // Existing fix is stale. + return true; + } + } + return false; +} + +bool GeolocationArbitratorImpl::HasPermissionBeenGranted() const { + return is_permission_granted_; +} + +} // namespace content |