Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/geolocation/network_location_provider.h" | 5 #include "device/geolocation/network_location_provider.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 const base::string16& access_token) | 110 const base::string16& access_token) |
| 111 : access_token_store_(access_token_store), | 111 : access_token_store_(access_token_store), |
| 112 wifi_data_provider_manager_(nullptr), | 112 wifi_data_provider_manager_(nullptr), |
| 113 wifi_data_update_callback_( | 113 wifi_data_update_callback_( |
| 114 base::Bind(&NetworkLocationProvider::OnWifiDataUpdate, | 114 base::Bind(&NetworkLocationProvider::OnWifiDataUpdate, |
| 115 base::Unretained(this))), | 115 base::Unretained(this))), |
| 116 is_wifi_data_complete_(false), | 116 is_wifi_data_complete_(false), |
| 117 access_token_(access_token), | 117 access_token_(access_token), |
| 118 is_permission_granted_(false), | 118 is_permission_granted_(false), |
| 119 is_new_data_available_(false), | 119 is_new_data_available_(false), |
| 120 request_(new NetworkLocationRequest( | |
| 121 url_context_getter, | |
| 122 url, | |
| 123 base::Bind(&NetworkLocationProvider::OnLocationResponse, | |
| 124 base::Unretained(this)))), | |
| 120 position_cache_(new PositionCache), | 125 position_cache_(new PositionCache), |
| 121 weak_factory_(this) { | 126 weak_factory_(this) { |
| 122 request_.reset(new NetworkLocationRequest( | 127 DLOG_IF(WARNING, url.is_valid()) |
| 123 url_context_getter, url, | 128 << __func__ << " Bad URL: " << url.possibly_invalid_spec(); |
| 124 base::Bind(&NetworkLocationProvider::OnLocationResponse, | |
| 125 base::Unretained(this)))); | |
| 126 } | 129 } |
| 127 | 130 |
| 128 NetworkLocationProvider::~NetworkLocationProvider() { | 131 NetworkLocationProvider::~NetworkLocationProvider() { |
| 129 StopProvider(); | 132 if (IsStarted()) |
| 130 } | 133 StopProvider(); |
| 131 | |
| 132 // LocationProvider implementation | |
| 133 const Geoposition& NetworkLocationProvider::GetPosition() { | |
| 134 return position_; | |
| 135 } | 134 } |
| 136 | 135 |
| 137 void NetworkLocationProvider::SetUpdateCallback( | 136 void NetworkLocationProvider::SetUpdateCallback( |
| 138 const LocationProvider::LocationProviderUpdateCallback& callback) { | 137 const LocationProvider::LocationProviderUpdateCallback& callback) { |
| 139 location_provider_update_callback_ = callback; | 138 location_provider_update_callback_ = callback; |
| 140 } | 139 } |
| 141 | 140 |
| 142 void NetworkLocationProvider::OnPermissionGranted() { | |
| 143 const bool was_permission_granted = is_permission_granted_; | |
| 144 is_permission_granted_ = true; | |
| 145 if (!was_permission_granted && IsStarted()) { | |
| 146 RequestPosition(); | |
| 147 } | |
| 148 } | |
| 149 | |
| 150 void NetworkLocationProvider::OnWifiDataUpdate() { | |
| 151 DCHECK(wifi_data_provider_manager_); | |
| 152 is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); | |
| 153 OnWifiDataUpdated(); | |
| 154 } | |
| 155 | |
| 156 void NetworkLocationProvider::OnLocationResponse( | |
| 157 const Geoposition& position, | |
| 158 bool server_error, | |
| 159 const base::string16& access_token, | |
| 160 const WifiData& wifi_data) { | |
| 161 DCHECK(CalledOnValidThread()); | |
| 162 // Record the position and update our cache. | |
| 163 position_ = position; | |
| 164 if (position.Validate()) { | |
| 165 position_cache_->CachePosition(wifi_data, position); | |
| 166 } | |
| 167 | |
| 168 // Record access_token if it's set. | |
| 169 if (!access_token.empty() && access_token_ != access_token) { | |
| 170 access_token_ = access_token; | |
| 171 access_token_store_->SaveAccessToken(request_->url(), access_token); | |
| 172 } | |
| 173 | |
| 174 // Let listeners know that we now have a position available. | |
| 175 if (!location_provider_update_callback_.is_null()) | |
| 176 location_provider_update_callback_.Run(this, position_); | |
| 177 } | |
| 178 | |
| 179 bool NetworkLocationProvider::StartProvider(bool high_accuracy) { | 141 bool NetworkLocationProvider::StartProvider(bool high_accuracy) { |
| 180 DCHECK(CalledOnValidThread()); | 142 DCHECK(thread_checker_.CalledOnValidThread()); |
| 181 if (IsStarted()) | 143 if (IsStarted()) |
| 182 return true; | 144 return true; |
| 183 DCHECK(!wifi_data_provider_manager_); | 145 |
| 184 if (!request_->url().is_valid()) { | 146 if (!request_->url().is_valid()) // Already DLOG() in constructor. |
|
dougt
2017/04/17 18:58:52
Have you considered just dropping this check? req
mcasas
2017/04/17 20:47:55
Changed to a DCHECK to document it as being a
pre
| |
| 185 LOG(WARNING) << "StartProvider() : Failed, Bad URL: " | |
| 186 << request_->url().possibly_invalid_spec(); | |
| 187 return false; | 147 return false; |
| 188 } | |
| 189 | 148 |
| 190 // Registers a callback with the data provider. The first call to Register | 149 // Registers a callback with the data provider. The first call to Register() |
| 191 // will create a singleton data provider and it will be deleted when the last | 150 // will create a singleton data provider that will be deleted on Unregister(). |
| 192 // callback is removed with Unregister. | |
| 193 wifi_data_provider_manager_ = | 151 wifi_data_provider_manager_ = |
| 194 WifiDataProviderManager::Register(&wifi_data_update_callback_); | 152 WifiDataProviderManager::Register(&wifi_data_update_callback_); |
| 195 | 153 |
| 196 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 154 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 197 FROM_HERE, base::Bind(&NetworkLocationProvider::RequestPosition, | 155 FROM_HERE, base::Bind(&NetworkLocationProvider::RequestPosition, |
| 198 weak_factory_.GetWeakPtr()), | 156 weak_factory_.GetWeakPtr()), |
| 199 base::TimeDelta::FromSeconds(kDataCompleteWaitSeconds)); | 157 base::TimeDelta::FromSeconds(kDataCompleteWaitSeconds)); |
| 200 // Get the wifi data. | 158 |
| 201 is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); | 159 OnWifiDataUpdate(); |
| 202 if (is_wifi_data_complete_) | |
| 203 OnWifiDataUpdated(); | |
| 204 return true; | 160 return true; |
| 205 } | 161 } |
| 206 | 162 |
| 207 void NetworkLocationProvider::OnWifiDataUpdated() { | |
| 208 DCHECK(CalledOnValidThread()); | |
| 209 wifi_timestamp_ = base::Time::Now(); | |
| 210 | |
| 211 is_new_data_available_ = is_wifi_data_complete_; | |
| 212 RequestPosition(); | |
| 213 } | |
| 214 | |
| 215 void NetworkLocationProvider::StopProvider() { | 163 void NetworkLocationProvider::StopProvider() { |
| 216 DCHECK(CalledOnValidThread()); | 164 DCHECK(thread_checker_.CalledOnValidThread()); |
| 217 if (IsStarted()) { | 165 DCHECK(IsStarted()); |
| 218 wifi_data_provider_manager_->Unregister(&wifi_data_update_callback_); | 166 wifi_data_provider_manager_->Unregister(&wifi_data_update_callback_); |
| 219 } | |
| 220 wifi_data_provider_manager_ = nullptr; | 167 wifi_data_provider_manager_ = nullptr; |
| 221 weak_factory_.InvalidateWeakPtrs(); | 168 weak_factory_.InvalidateWeakPtrs(); |
| 222 } | 169 } |
| 223 | 170 |
| 224 // Other methods | 171 const Geoposition& NetworkLocationProvider::GetPosition() { |
| 172 return position_; | |
| 173 } | |
| 174 | |
| 175 void NetworkLocationProvider::OnPermissionGranted() { | |
| 176 const bool was_permission_granted = is_permission_granted_; | |
| 177 is_permission_granted_ = true; | |
| 178 if (!was_permission_granted && IsStarted()) | |
| 179 RequestPosition(); | |
| 180 } | |
| 181 | |
| 225 void NetworkLocationProvider::RequestPosition() { | 182 void NetworkLocationProvider::RequestPosition() { |
| 226 DCHECK(CalledOnValidThread()); | 183 DCHECK(thread_checker_.CalledOnValidThread()); |
| 227 | 184 |
| 228 // TODO(mcasas): consider not using HasWeakPtrs() https://crbug.com/629158. | 185 if (!is_new_data_available_ || !is_wifi_data_complete_) |
| 229 if (weak_factory_.HasWeakPtrs() && !is_wifi_data_complete_) | |
| 230 return; | 186 return; |
| 231 if (!is_new_data_available_) | 187 DCHECK(!wifi_timestamp_.is_null()) |
| 232 return; | 188 << "|wifi_timestamp_| must be set before looking up position"; |
| 233 | 189 |
| 234 const Geoposition* cached_position = | 190 const Geoposition* cached_position = |
| 235 position_cache_->FindPosition(wifi_data_); | 191 position_cache_->FindPosition(wifi_data_); |
| 236 DCHECK(!wifi_timestamp_.is_null()) | |
| 237 << "Timestamp must be set before looking up position"; | |
| 238 if (cached_position) { | 192 if (cached_position) { |
| 239 DCHECK(cached_position->Validate()); | 193 DCHECK(cached_position->Validate()); |
| 240 // Record the position and update its timestamp. | 194 // Record the position and update its timestamp. |
| 241 position_ = *cached_position; | 195 position_ = *cached_position; |
| 242 | 196 |
| 243 // The timestamp of a position fix is determined by the timestamp | 197 // The timestamp of a position fix is determined by the timestamp |
| 244 // of the source data update. (The value of position_.timestamp from | 198 // of the source data update. (The value of position_.timestamp from |
| 245 // the cache could be from weeks ago!) | 199 // the cache could be from weeks ago!) |
| 246 position_.timestamp = wifi_timestamp_; | 200 position_.timestamp = wifi_timestamp_; |
| 247 is_new_data_available_ = false; | 201 is_new_data_available_ = false; |
| 248 | 202 |
| 249 // Let listeners know that we now have a position available. | 203 // Let listeners know that we now have a position available. |
| 250 if (!location_provider_update_callback_.is_null()) | 204 if (!location_provider_update_callback_.is_null()) |
| 251 location_provider_update_callback_.Run(this, position_); | 205 location_provider_update_callback_.Run(this, position_); |
| 252 return; | 206 return; |
| 253 } | 207 } |
| 208 | |
| 254 // Don't send network requests until authorized. http://crbug.com/39171 | 209 // Don't send network requests until authorized. http://crbug.com/39171 |
| 255 if (!is_permission_granted_) | 210 if (!is_permission_granted_) |
| 256 return; | 211 return; |
| 257 | 212 |
| 258 weak_factory_.InvalidateWeakPtrs(); | |
| 259 is_new_data_available_ = false; | 213 is_new_data_available_ = false; |
| 260 | 214 |
| 261 // TODO(joth): Rather than cancel pending requests, we should create a new | 215 // TODO(joth): Rather than cancel pending requests, we should create a new |
| 262 // NetworkLocationRequest for each and hold a set of pending requests. | 216 // NetworkLocationRequest for each and hold a set of pending requests. |
| 217 #if !defined(NDEBUG) | |
| 263 if (request_->is_request_pending()) { | 218 if (request_->is_request_pending()) { |
| 264 DVLOG(1) << "NetworkLocationProvider - pre-empting pending network request " | 219 DVLOG(1) << "NetworkLocationProvider - pre-empting pending network request " |
|
dougt
2017/04/17 18:58:52
is this DVLOG() needed anymore? Maybe just drop i
mcasas
2017/04/17 20:47:55
Hmm well, I didn't want to remove it entirely beca
| |
| 265 "with new data. Wifi APs: " | 220 "with new data. Wifi APs: " |
| 266 << wifi_data_.access_point_data.size(); | 221 << wifi_data_.access_point_data.size(); |
| 267 } | 222 } |
| 223 #endif | |
| 268 request_->MakeRequest(access_token_, wifi_data_, wifi_timestamp_); | 224 request_->MakeRequest(access_token_, wifi_data_, wifi_timestamp_); |
| 269 } | 225 } |
| 270 | 226 |
| 227 void NetworkLocationProvider::OnWifiDataUpdate() { | |
| 228 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 229 DCHECK(IsStarted()); | |
| 230 is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); | |
| 231 if (!is_wifi_data_complete_) | |
| 232 return; | |
| 233 | |
| 234 wifi_timestamp_ = base::Time::Now(); | |
| 235 is_new_data_available_ = true; | |
| 236 RequestPosition(); | |
| 237 } | |
| 238 | |
| 271 bool NetworkLocationProvider::IsStarted() const { | 239 bool NetworkLocationProvider::IsStarted() const { |
| 272 return wifi_data_provider_manager_ != nullptr; | 240 return wifi_data_provider_manager_ != nullptr; |
| 273 } | 241 } |
| 274 | 242 |
| 243 void NetworkLocationProvider::OnLocationResponse( | |
| 244 const Geoposition& position, | |
| 245 bool server_error, | |
| 246 const base::string16& access_token, | |
| 247 const WifiData& wifi_data) { | |
| 248 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 249 // Record the position and update our cache. | |
| 250 position_ = position; | |
|
dougt
2017/04/17 18:58:52
I am confused why this code remembers the position
mcasas
2017/04/17 20:47:55
Bug perhaps? I haven't changed this method's logic
| |
| 251 if (position.Validate()) | |
| 252 position_cache_->CachePosition(wifi_data, position); | |
| 253 | |
| 254 // Record access_token if it's set. | |
| 255 if (!access_token.empty() && access_token_ != access_token) { | |
| 256 access_token_ = access_token; | |
| 257 access_token_store_->SaveAccessToken(request_->url(), access_token); | |
| 258 } | |
| 259 | |
| 260 // Let listeners know that we now have a position available. | |
| 261 if (!location_provider_update_callback_.is_null()) | |
| 262 location_provider_update_callback_.Run(this, position_); | |
| 263 } | |
| 264 | |
| 275 } // namespace device | 265 } // namespace device |
| OLD | NEW |