OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/geolocation/location_arbitrator.h" | |
6 | |
7 #include <map> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/bind_helpers.h" | |
11 #include "content/public/browser/access_token_store.h" | |
12 #include "content/public/browser/content_browser_client.h" | |
13 #include "content/public/common/content_client.h" | |
14 #include "googleurl/src/gurl.h" | |
15 | |
16 namespace content { | |
17 namespace { | |
18 | |
19 const char* kDefaultNetworkProviderUrl = | |
20 "https://www.googleapis.com/geolocation/v1/geolocate"; | |
21 } // namespace | |
22 | |
23 // To avoid oscillations, set this to twice the expected update interval of a | |
24 // a GPS-type location provider (in case it misses a beat) plus a little. | |
25 const int64 GeolocationArbitrator::kFixStaleTimeoutMilliseconds = | |
26 11 * base::Time::kMillisecondsPerSecond; | |
27 | |
28 GeolocationArbitrator::GeolocationArbitrator( | |
29 GeolocationObserver* observer) | |
30 : observer_(observer), | |
31 position_provider_(NULL), | |
32 is_permission_granted_(false) { | |
33 } | |
34 | |
35 GeolocationArbitrator::~GeolocationArbitrator() { | |
36 } | |
37 | |
38 GURL GeolocationArbitrator::DefaultNetworkProviderURL() { | |
39 return GURL(kDefaultNetworkProviderUrl); | |
40 } | |
41 | |
42 void GeolocationArbitrator::OnPermissionGranted() { | |
43 is_permission_granted_ = true; | |
44 for (ScopedVector<LocationProviderBase>::iterator i = providers_.begin(); | |
45 i != providers_.end(); ++i) { | |
46 (*i)->OnPermissionGranted(); | |
47 } | |
48 } | |
49 | |
50 void GeolocationArbitrator::StartProviders( | |
51 const GeolocationObserverOptions& options) { | |
52 // Stash options as OnAccessTokenStoresLoaded has not yet been called. | |
53 current_provider_options_ = options; | |
54 if (providers_.empty()) { | |
55 DCHECK(DefaultNetworkProviderURL().is_valid()); | |
56 GetAccessTokenStore()->LoadAccessTokens( | |
57 base::Bind(&GeolocationArbitrator::OnAccessTokenStoresLoaded, | |
58 base::Unretained(this))); | |
59 } else { | |
60 DoStartProviders(); | |
61 } | |
62 } | |
63 | |
64 void GeolocationArbitrator::DoStartProviders() { | |
65 for (ScopedVector<LocationProviderBase>::iterator i = providers_.begin(); | |
66 i != providers_.end(); ++i) { | |
67 (*i)->StartProvider(current_provider_options_.use_high_accuracy); | |
68 } | |
69 } | |
70 | |
71 void GeolocationArbitrator::StopProviders() { | |
72 providers_.clear(); | |
73 } | |
74 | |
75 void GeolocationArbitrator::OnAccessTokenStoresLoaded( | |
76 AccessTokenStore::AccessTokenSet access_token_set, | |
77 net::URLRequestContextGetter* context_getter) { | |
78 if (!providers_.empty()) { | |
79 // A second StartProviders() call may have arrived before the first | |
80 // completed. | |
81 return; | |
82 } | |
83 // If there are no access tokens, boot strap it with the default server URL. | |
84 if (access_token_set.empty()) | |
85 access_token_set[DefaultNetworkProviderURL()]; | |
86 for (AccessTokenStore::AccessTokenSet::iterator i = | |
87 access_token_set.begin(); | |
88 i != access_token_set.end(); ++i) { | |
89 RegisterProvider( | |
90 NewNetworkLocationProvider( | |
91 GetAccessTokenStore(), context_getter, | |
92 i->first, i->second)); | |
93 } | |
94 RegisterProvider(NewSystemLocationProvider()); | |
95 DoStartProviders(); | |
96 } | |
97 | |
98 void GeolocationArbitrator::RegisterProvider( | |
99 LocationProviderBase* provider) { | |
100 if (!provider) | |
101 return; | |
102 provider->RegisterListener(this); | |
103 if (is_permission_granted_) | |
104 provider->OnPermissionGranted(); | |
105 providers_.push_back(provider); | |
106 } | |
107 | |
108 void GeolocationArbitrator::LocationUpdateAvailable( | |
109 LocationProviderBase* provider) { | |
110 DCHECK(provider); | |
111 Geoposition new_position; | |
112 provider->GetPosition(&new_position); | |
113 DCHECK(new_position.Validate() || | |
114 new_position.error_code != Geoposition::ERROR_CODE_NONE); | |
115 if (!IsNewPositionBetter(position_, new_position, | |
116 provider == position_provider_)) | |
117 return; | |
118 position_provider_ = provider; | |
119 position_ = new_position; | |
120 observer_->OnLocationUpdate(position_); | |
121 } | |
122 | |
123 AccessTokenStore* GeolocationArbitrator::NewAccessTokenStore() { | |
124 return GetContentClient()->browser()->CreateAccessTokenStore(); | |
125 } | |
126 | |
127 AccessTokenStore* GeolocationArbitrator::GetAccessTokenStore() { | |
128 if (!access_token_store_.get()) | |
129 access_token_store_ = NewAccessTokenStore(); | |
130 return access_token_store_.get(); | |
131 } | |
132 | |
133 LocationProviderBase* GeolocationArbitrator::NewNetworkLocationProvider( | |
134 AccessTokenStore* access_token_store, | |
135 net::URLRequestContextGetter* context, | |
136 const GURL& url, | |
137 const string16& access_token) { | |
138 #if defined(OS_ANDROID) | |
139 // Android uses its own SystemLocationProvider. | |
140 return NULL; | |
141 #else | |
142 return content::NewNetworkLocationProvider(access_token_store, context, url, | |
143 access_token); | |
144 #endif | |
145 } | |
146 | |
147 LocationProviderBase* GeolocationArbitrator::NewSystemLocationProvider() { | |
148 return content::NewSystemLocationProvider(); | |
149 } | |
150 | |
151 base::Time GeolocationArbitrator::GetTimeNow() const { | |
152 return base::Time::Now(); | |
153 } | |
154 | |
155 bool GeolocationArbitrator::IsNewPositionBetter( | |
156 const Geoposition& old_position, const Geoposition& new_position, | |
157 bool from_same_provider) const { | |
158 // Updates location_info if it's better than what we currently have, | |
159 // or if it's a newer update from the same provider. | |
160 if (!old_position.Validate()) { | |
161 // Older location wasn't locked. | |
162 return true; | |
163 } | |
164 if (new_position.Validate()) { | |
165 // New location is locked, let's check if it's any better. | |
166 if (old_position.accuracy >= new_position.accuracy) { | |
167 // Accuracy is better. | |
168 return true; | |
169 } else if (from_same_provider) { | |
170 // Same provider, fresher location. | |
171 return true; | |
172 } else if ((GetTimeNow() - old_position.timestamp).InMilliseconds() > | |
173 kFixStaleTimeoutMilliseconds) { | |
174 // Existing fix is stale. | |
175 return true; | |
176 } | |
177 } | |
178 return false; | |
179 } | |
180 | |
181 bool GeolocationArbitrator::HasPermissionBeenGranted() const { | |
182 return is_permission_granted_; | |
183 } | |
184 | |
185 } // namespace content | |
OLD | NEW |