15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/geolocation/network_location_provider.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/access_token_store.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// The maximum period of time we'll wait for a complete set of wifi data 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before sending the request. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDataCompleteWaitSeconds = 2; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t NetworkLocationProvider::PositionCache::kMaximumSize = 10; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkLocationProvider::PositionCache::PositionCache() {} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkLocationProvider::PositionCache::~PositionCache() {} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetworkLocationProvider::PositionCache::CachePosition( 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WifiData& wifi_data, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Geoposition& position) { 29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Check that we can generate a valid key for the wifi data. 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 key; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!MakeKey(wifi_data, &key)) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the cache is full, remove the oldest entry. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cache_.size() == kMaximumSize) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cache_age_list_.size() == kMaximumSize); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CacheAgeList::iterator oldest_entry = cache_age_list_.begin(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(oldest_entry != cache_age_list_.end()); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.erase(*oldest_entry); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_age_list_.erase(oldest_entry); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(cache_.size(), kMaximumSize); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert the position into the cache. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<CacheMap::iterator, bool> result = 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.insert(std::make_pair(key, position)); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result.second) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); // We never try to add the same key twice. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(cache_.size(), cache_age_list_.size()); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_age_list_.push_back(result.first); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(cache_.size(), cache_age_list_.size()); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Searches for a cached position response for the current WiFi data. Returns 57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// the cached position if available, NULL otherwise. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Geoposition* NetworkLocationProvider::PositionCache::FindPosition( 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WifiData& wifi_data) { 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 key; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!MakeKey(wifi_data, &key)) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CacheMap::const_iterator iter = cache_.find(key); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return iter == cache_.end() ? NULL : &iter->second; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Makes the key for the map of cached positions, using the available data. 69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Returns true if a good key was generated, false otherwise. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetworkLocationProvider::PositionCache::MakeKey( 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WifiData& wifi_data, 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16* key) { 75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Currently we use only WiFi data and base the key only on the MAC addresses. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(key); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key->clear(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t kCharsPerMacAddress = 6 * 3 + 1; // e.g. "11:22:33:44:55:66|" 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key->reserve(wifi_data.access_point_data.size() * kCharsPerMacAddress); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16 separator(base::ASCIIToUTF16("|")); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (WifiData::AccessPointDataSet::const_iterator iter = 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wifi_data.access_point_data.begin(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != wifi_data.access_point_data.end(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter++) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *key += separator; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *key += iter->mac_address; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *key += separator; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the key is the empty string, return false, as we don't want to cache a 90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // position for such data. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !key->empty(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NetworkLocationProvider factory function 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LocationProviderBase* NewNetworkLocationProvider( 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AccessTokenStore* access_token_store, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* context, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& access_token) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new NetworkLocationProvider( 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) access_token_store, context, url, access_token); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NetworkLocationProvider 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkLocationProvider::NetworkLocationProvider( 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AccessTokenStore* access_token_store, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* url_context_getter, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& access_token) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : access_token_store_(access_token_store), 11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) wifi_data_provider_manager_(NULL), 112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) wifi_data_update_callback_( 1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Bind(&NetworkLocationProvider::OnWifiDataUpdate, 114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::Unretained(this))), 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_wifi_data_complete_(false), 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) access_token_(access_token), 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_permission_granted_(false), 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_new_data_available_(false), 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the position cache. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position_cache_.reset(new PositionCache()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) request_.reset(new NetworkLocationRequest( 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) url_context_getter, 1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) url, 1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Bind(&NetworkLocationProvider::OnLocationResponse, 1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Unretained(this)))); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkLocationProvider::~NetworkLocationProvider() { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopProvider(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// LocationProvider implementation 135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void NetworkLocationProvider::GetPosition(Geoposition* position) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(position); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *position = position_; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void NetworkLocationProvider::RequestRefresh() { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(joth): When called via the public (base class) interface, this should 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // poke each data provider to get them to expedite their next scan. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Whilst in the delayed start, only send request if all data is ready. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!weak_factory_.HasWeakPtrs() || is_wifi_data_complete_) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestPosition(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkLocationProvider::OnPermissionGranted() { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool was_permission_granted = is_permission_granted_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_permission_granted_ = true; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!was_permission_granted && IsStarted()) { 1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RequestRefresh(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void NetworkLocationProvider::OnWifiDataUpdate() { 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(wifi_data_provider_manager_); 15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); 160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) OnWifiDataUpdated(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void NetworkLocationProvider::OnLocationResponse( 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Geoposition& position, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool server_error, 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& access_token, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WifiData& wifi_data) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record the position and update our cache. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position_ = position; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (position.Validate()) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position_cache_->CachePosition(wifi_data, position); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record access_token if it's set. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!access_token.empty() && access_token_ != access_token) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) access_token_ = access_token; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) access_token_store_->SaveAccessToken(request_->url(), access_token); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let listeners know that we now have a position available. 1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NotifyCallback(position_); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetworkLocationProvider::StartProvider(bool high_accuracy) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsStarted()) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(wifi_data_provider_manager_ == NULL); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!request_->url().is_valid()) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "StartProvider() : Failed, Bad URL: " 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << request_->url().possibly_invalid_spec(); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Registers a callback with the data provider. The first call to Register 197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // will create a singleton data provider and it will be deleted when the last 198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // callback is removed with Unregister. 19903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) wifi_data_provider_manager_ = 20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) WifiDataProviderManager::Register(&wifi_data_update_callback_); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetworkLocationProvider::RequestPosition, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.GetWeakPtr()), 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kDataCompleteWaitSeconds)); 207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Get the wifi data. 20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_wifi_data_complete_) 210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) OnWifiDataUpdated(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void NetworkLocationProvider::OnWifiDataUpdated() { 215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(CalledOnValidThread()); 216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) wifi_data_updated_timestamp_ = base::Time::Now(); 217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) is_new_data_available_ = is_wifi_data_complete_; 219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) RequestRefresh(); 220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkLocationProvider::StopProvider() { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsStarted()) { 22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) wifi_data_provider_manager_->Unregister(&wifi_data_update_callback_); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) wifi_data_provider_manager_ = NULL; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Other methods 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkLocationProvider::RequestPosition() { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_new_data_available_) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Geoposition* cached_position = 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position_cache_->FindPosition(wifi_data_); 239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(!wifi_data_updated_timestamp_.is_null()) << 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Timestamp must be set before looking up position"; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cached_position) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cached_position->Validate()); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record the position and update its timestamp. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position_ = *cached_position; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The timestamp of a position fix is determined by the timestamp 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the source data update. (The value of position_.timestamp from 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the cache could be from weeks ago!) 248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) position_.timestamp = wifi_data_updated_timestamp_; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_new_data_available_ = false; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let listeners know that we now have a position available. 2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NotifyCallback(position_); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't send network requests until authorized. http://crbug.com/39171 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_permission_granted_) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_new_data_available_ = false; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(joth): Rather than cancel pending requests, we should create a new 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NetworkLocationRequest for each and hold a set of pending requests. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request_->is_request_pending()) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "NetworkLocationProvider - pre-empting pending network request " 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "with new data. Wifi APs: " 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << wifi_data_.access_point_data.size(); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->MakeRequest(access_token_, wifi_data_, 269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) wifi_data_updated_timestamp_); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetworkLocationProvider::IsStarted() const { 27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return wifi_data_provider_manager_ != NULL; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 277