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)// Provides wifi scan API binding for chromeos, using proprietary APIs. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/geolocation/wifi_data_provider_chromeos.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/geolocation_handler.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The time periods between successive polls of the wifi data. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultPollingIntervalMilliseconds = 10 * 1000; // 10s 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNoChangePollingIntervalMilliseconds = 2 * 60 * 1000; // 2 mins 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTwoNoChangePollingIntervalMilliseconds = 10 * 60 * 1000; // 10 mins 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNoWifiPollingIntervalMilliseconds = 20 * 1000; // 20s 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WifiDataProviderChromeOs::WifiDataProviderChromeOs() : started_(false) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WifiDataProviderChromeOs::~WifiDataProviderChromeOs() { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WifiDataProviderChromeOs::StartDataProvider() { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnClientThread()); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(polling_policy_ == NULL); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) polling_policy_.reset( 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new GenericPollingPolicy<kDefaultPollingIntervalMilliseconds, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kNoChangePollingIntervalMilliseconds, 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kTwoNoChangePollingIntervalMilliseconds, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kNoWifiPollingIntervalMilliseconds>); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleStart(); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WifiDataProviderChromeOs::StopDataProvider() { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnClientThread()); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) polling_policy_.reset(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleStop(); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WifiDataProviderChromeOs::GetData(WifiData* data) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnClientThread()); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *data = wifi_data_; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_first_scan_complete_; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WifiDataProviderChromeOs::DoStartTaskOnUIThread() { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoWifiScanTaskOnUIThread(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WifiDataProviderChromeOs::DoWifiScanTaskOnUIThread() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This method could be scheduled after a ScheduleStop. 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!started_) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WifiData new_data; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetAccessPointData(&new_data.access_point_data)) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_loop()->PostTask( 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&WifiDataProviderChromeOs::DidWifiScanTaskNoResults, this)); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_loop()->PostTask( 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&WifiDataProviderChromeOs::DidWifiScanTask, this, new_data)); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WifiDataProviderChromeOs::DidWifiScanTaskNoResults() { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnClientThread()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule next scan if started (StopDataProvider could have been called 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in between DoWifiScanTaskOnUIThread and this method). 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started_) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleNextScan(polling_policy_->NoWifiInterval()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MaybeNotifyListeners(false); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WifiDataProviderChromeOs::DidWifiScanTask(const WifiData& new_data) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnClientThread()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool update_available = wifi_data_.DiffersSignificantly(new_data); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wifi_data_ = new_data; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule next scan if started (StopDataProvider could have been called 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in between DoWifiScanTaskOnUIThread and this method). 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started_) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) polling_policy_->UpdatePollingInterval(update_available); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleNextScan(polling_policy_->PollingInterval()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MaybeNotifyListeners(update_available); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WifiDataProviderChromeOs::MaybeNotifyListeners(bool update_available) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (update_available || !is_first_scan_complete_) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_first_scan_complete_ = true; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyListeners(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WifiDataProviderChromeOs::ScheduleNextScan(int interval) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnClientThread()); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(started_); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostDelayedTask( 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&WifiDataProviderChromeOs::DoWifiScanTaskOnUIThread, this), 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(interval)); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WifiDataProviderChromeOs::ScheduleStop() { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnClientThread()); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(started_); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_ = false; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WifiDataProviderChromeOs::ScheduleStart() { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnClientThread()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!started_); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_ = true; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Perform first scan ASAP regardless of the polling policy. If this scan 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fails we'll retry at a rate in line with the polling policy. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&WifiDataProviderChromeOs::DoStartTaskOnUIThread, this)); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WifiDataProviderChromeOs::GetAccessPointData( 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WifiData::AccessPointDataSet* result) { 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::WifiAccessPointVector access_points; 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!chromeos::NetworkHandler::Get()->geolocation_handler()->wifi_enabled()) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 age_ms = 0; 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!chromeos::NetworkHandler::Get()->geolocation_handler()-> 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GetWifiAccessPoints(&access_points, &age_ms)) { 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (chromeos::WifiAccessPointVector::const_iterator i 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) = access_points.begin(); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i != access_points.end(); ++i) { 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AccessPointData ap_data; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ap_data.mac_address = ASCIIToUTF16(i->mac_address); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ap_data.radio_signal_strength = i->signal_strength; 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ap_data.channel = i->channel; 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ap_data.signal_to_noise = i->signal_to_noise; 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ap_data.ssid = UTF8ToUTF16(i->ssid); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->insert(ap_data); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the age is significantly longer than our long polling time, assume the 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // data is stale and return false which will trigger a faster update. 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (age_ms > kTwoNoChangePollingIntervalMilliseconds * 2) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<> 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() { 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new WifiDataProviderChromeOs(); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace content 177