summaryrefslogtreecommitdiffstats
path: root/content/browser/geolocation/location_arbitrator_impl.cc
diff options
context:
space:
mode:
authorjknotten@chromium.org <jknotten@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-30 13:00:40 +0000
committerjknotten@chromium.org <jknotten@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-30 13:00:40 +0000
commit90984b00d84729a170cdb6a2b863e47b15ff7aea (patch)
tree0969d0390030262306593d5905e40e95c44ce831 /content/browser/geolocation/location_arbitrator_impl.cc
parentbade57cab535b5459975b44ea4e85362c576deea (diff)
downloadchromium_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.cc185
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