| 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 DCHECK(thread_checker_.CalledOnValidThread()); |
| 130 } | 133 if (IsStarted()) |
| 131 | 134 StopProvider(); |
| 132 // LocationProvider implementation | |
| 133 const Geoposition& NetworkLocationProvider::GetPosition() { | |
| 134 return position_; | |
| 135 } | 135 } |
| 136 | 136 |
| 137 void NetworkLocationProvider::SetUpdateCallback( | 137 void NetworkLocationProvider::SetUpdateCallback( |
| 138 const LocationProvider::LocationProviderUpdateCallback& callback) { | 138 const LocationProvider::LocationProviderUpdateCallback& callback) { |
| 139 DCHECK(thread_checker_.CalledOnValidThread()); |
| 139 location_provider_update_callback_ = callback; | 140 location_provider_update_callback_ = callback; |
| 140 } | 141 } |
| 141 | 142 |
| 142 void NetworkLocationProvider::OnPermissionGranted() { | 143 void NetworkLocationProvider::OnPermissionGranted() { |
| 143 const bool was_permission_granted = is_permission_granted_; | 144 const bool was_permission_granted = is_permission_granted_; |
| 144 is_permission_granted_ = true; | 145 is_permission_granted_ = true; |
| 145 if (!was_permission_granted && IsStarted()) { | 146 if (!was_permission_granted && IsStarted()) |
| 146 RequestPosition(); | 147 RequestPosition(); |
| 147 } | |
| 148 } | 148 } |
| 149 | 149 |
| 150 void NetworkLocationProvider::OnWifiDataUpdate() { | 150 void NetworkLocationProvider::OnWifiDataUpdate() { |
| 151 DCHECK(wifi_data_provider_manager_); | 151 DCHECK(thread_checker_.CalledOnValidThread()); |
| 152 DCHECK(IsStarted()); |
| 152 is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); | 153 is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); |
| 153 OnWifiDataUpdated(); | 154 if (!is_wifi_data_complete_) |
| 155 return; |
| 156 |
| 157 wifi_timestamp_ = base::Time::Now(); |
| 158 is_new_data_available_ = true; |
| 159 RequestPosition(); |
| 154 } | 160 } |
| 155 | 161 |
| 156 void NetworkLocationProvider::OnLocationResponse( | 162 void NetworkLocationProvider::OnLocationResponse( |
| 157 const Geoposition& position, | 163 const Geoposition& position, |
| 158 bool server_error, | 164 bool server_error, |
| 159 const base::string16& access_token, | 165 const base::string16& access_token, |
| 160 const WifiData& wifi_data) { | 166 const WifiData& wifi_data) { |
| 161 DCHECK(CalledOnValidThread()); | 167 DCHECK(thread_checker_.CalledOnValidThread()); |
| 162 // Record the position and update our cache. | 168 // Record the position and update our cache. |
| 163 position_ = position; | 169 position_ = position; |
| 164 if (position.Validate()) { | 170 if (position.Validate()) |
| 165 position_cache_->CachePosition(wifi_data, position); | 171 position_cache_->CachePosition(wifi_data, position); |
| 166 } | |
| 167 | 172 |
| 168 // Record access_token if it's set. | 173 // Record access_token if it's set. |
| 169 if (!access_token.empty() && access_token_ != access_token) { | 174 if (!access_token.empty() && access_token_ != access_token) { |
| 170 access_token_ = access_token; | 175 access_token_ = access_token; |
| 171 access_token_store_->SaveAccessToken(request_->url(), access_token); | 176 access_token_store_->SaveAccessToken(request_->url(), access_token); |
| 172 } | 177 } |
| 173 | 178 |
| 174 // Let listeners know that we now have a position available. | 179 // Let listeners know that we now have a position available. |
| 175 if (!location_provider_update_callback_.is_null()) | 180 if (!location_provider_update_callback_.is_null()) |
| 176 location_provider_update_callback_.Run(this, position_); | 181 location_provider_update_callback_.Run(this, position_); |
| 177 } | 182 } |
| 178 | 183 |
| 179 bool NetworkLocationProvider::StartProvider(bool high_accuracy) { | 184 bool NetworkLocationProvider::StartProvider(bool high_accuracy) { |
| 180 DCHECK(CalledOnValidThread()); | 185 DCHECK(thread_checker_.CalledOnValidThread()); |
| 181 if (IsStarted()) | 186 if (IsStarted()) |
| 182 return true; | 187 return true; |
| 183 DCHECK(!wifi_data_provider_manager_); | 188 if (!request_->url().is_valid()) |
| 184 if (!request_->url().is_valid()) { | |
| 185 LOG(WARNING) << "StartProvider() : Failed, Bad URL: " | |
| 186 << request_->url().possibly_invalid_spec(); | |
| 187 return false; | 189 return false; |
| 188 } | |
| 189 | 190 |
| 190 // Registers a callback with the data provider. The first call to Register | 191 // 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 | 192 // will create a singleton data provider that will be deleted on Unregister(). |
| 192 // callback is removed with Unregister. | |
| 193 wifi_data_provider_manager_ = | 193 wifi_data_provider_manager_ = |
| 194 WifiDataProviderManager::Register(&wifi_data_update_callback_); | 194 WifiDataProviderManager::Register(&wifi_data_update_callback_); |
| 195 | 195 |
| 196 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 196 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 197 FROM_HERE, base::Bind(&NetworkLocationProvider::RequestPosition, | 197 FROM_HERE, base::Bind(&NetworkLocationProvider::RequestPosition, |
| 198 weak_factory_.GetWeakPtr()), | 198 weak_factory_.GetWeakPtr()), |
| 199 base::TimeDelta::FromSeconds(kDataCompleteWaitSeconds)); | 199 base::TimeDelta::FromSeconds(kDataCompleteWaitSeconds)); |
| 200 // Get the wifi data. | 200 |
| 201 is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); | 201 OnWifiDataUpdate(); |
| 202 if (is_wifi_data_complete_) | |
| 203 OnWifiDataUpdated(); | |
| 204 return true; | 202 return true; |
| 205 } | 203 } |
| 206 | 204 |
| 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() { | 205 void NetworkLocationProvider::StopProvider() { |
| 216 DCHECK(CalledOnValidThread()); | 206 DCHECK(thread_checker_.CalledOnValidThread()); |
| 217 if (IsStarted()) { | 207 DCHECK(IsStarted()); |
| 218 wifi_data_provider_manager_->Unregister(&wifi_data_update_callback_); | 208 wifi_data_provider_manager_->Unregister(&wifi_data_update_callback_); |
| 219 } | |
| 220 wifi_data_provider_manager_ = nullptr; | 209 wifi_data_provider_manager_ = nullptr; |
| 221 weak_factory_.InvalidateWeakPtrs(); | 210 weak_factory_.InvalidateWeakPtrs(); |
| 222 } | 211 } |
| 223 | 212 |
| 224 // Other methods | 213 const Geoposition& NetworkLocationProvider::GetPosition() { |
| 214 return position_; |
| 215 } |
| 216 |
| 225 void NetworkLocationProvider::RequestPosition() { | 217 void NetworkLocationProvider::RequestPosition() { |
| 226 DCHECK(CalledOnValidThread()); | 218 DCHECK(thread_checker_.CalledOnValidThread()); |
| 227 | 219 |
| 228 // TODO(mcasas): consider not using HasWeakPtrs() https://crbug.com/629158. | 220 if (!is_new_data_available_ || !is_wifi_data_complete_) |
| 229 if (weak_factory_.HasWeakPtrs() && !is_wifi_data_complete_) | |
| 230 return; | 221 return; |
| 231 if (!is_new_data_available_) | 222 DCHECK(!wifi_timestamp_.is_null()) |
| 232 return; | 223 << "|wifi_timestamp_| must be set before looking up position"; |
| 233 | 224 |
| 234 const Geoposition* cached_position = | 225 const Geoposition* cached_position = |
| 235 position_cache_->FindPosition(wifi_data_); | 226 position_cache_->FindPosition(wifi_data_); |
| 236 DCHECK(!wifi_timestamp_.is_null()) | |
| 237 << "Timestamp must be set before looking up position"; | |
| 238 if (cached_position) { | 227 if (cached_position) { |
| 239 DCHECK(cached_position->Validate()); | 228 DCHECK(cached_position->Validate()); |
| 240 // Record the position and update its timestamp. | 229 // Record the position and update its timestamp. |
| 241 position_ = *cached_position; | 230 position_ = *cached_position; |
| 242 | 231 |
| 243 // The timestamp of a position fix is determined by the timestamp | 232 // The timestamp of a position fix is determined by the timestamp |
| 244 // of the source data update. (The value of position_.timestamp from | 233 // of the source data update. (The value of position_.timestamp from |
| 245 // the cache could be from weeks ago!) | 234 // the cache could be from weeks ago!) |
| 246 position_.timestamp = wifi_timestamp_; | 235 position_.timestamp = wifi_timestamp_; |
| 247 is_new_data_available_ = false; | 236 is_new_data_available_ = false; |
| 248 | 237 |
| 249 // Let listeners know that we now have a position available. | 238 // Let listeners know that we now have a position available. |
| 250 if (!location_provider_update_callback_.is_null()) | 239 if (!location_provider_update_callback_.is_null()) |
| 251 location_provider_update_callback_.Run(this, position_); | 240 location_provider_update_callback_.Run(this, position_); |
| 252 return; | 241 return; |
| 253 } | 242 } |
| 254 // Don't send network requests until authorized. http://crbug.com/39171 | 243 // Don't send network requests until authorized. http://crbug.com/39171 |
| 255 if (!is_permission_granted_) | 244 if (!is_permission_granted_) |
| 256 return; | 245 return; |
| 257 | 246 |
| 258 weak_factory_.InvalidateWeakPtrs(); | |
| 259 is_new_data_available_ = false; | 247 is_new_data_available_ = false; |
| 260 | 248 |
| 261 // TODO(joth): Rather than cancel pending requests, we should create a new | 249 // TODO(joth): Rather than cancel pending requests, we should create a new |
| 262 // NetworkLocationRequest for each and hold a set of pending requests. | 250 // NetworkLocationRequest for each and hold a set of pending requests. |
| 263 if (request_->is_request_pending()) { | 251 DLOG_IF(WARNING, request_->is_request_pending()) |
| 264 DVLOG(1) << "NetworkLocationProvider - pre-empting pending network request " | 252 << "NetworkLocationProvider - pre-empting pending network request " |
| 265 "with new data. Wifi APs: " | 253 "with new data. Wifi APs: " |
| 266 << wifi_data_.access_point_data.size(); | 254 << wifi_data_.access_point_data.size(); |
| 267 } | 255 |
| 268 request_->MakeRequest(access_token_, wifi_data_, wifi_timestamp_); | 256 request_->MakeRequest(access_token_, wifi_data_, wifi_timestamp_); |
| 269 } | 257 } |
| 270 | 258 |
| 271 bool NetworkLocationProvider::IsStarted() const { | 259 bool NetworkLocationProvider::IsStarted() const { |
| 272 return wifi_data_provider_manager_ != nullptr; | 260 return wifi_data_provider_manager_ != nullptr; |
| 273 } | 261 } |
| 274 | 262 |
| 275 } // namespace device | 263 } // namespace device |
| OLD | NEW |