Home | History | Annotate | Download | only in geolocation
      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 // Provides wifi scan API binding for chromeos, using proprietary APIs.
      6 
      7 #include "content/browser/geolocation/wifi_data_provider_chromeos.h"
      8 
      9 #include "base/bind.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "chromeos/network/geolocation_handler.h"
     12 #include "content/browser/geolocation/wifi_data_provider_manager.h"
     13 #include "content/public/browser/browser_thread.h"
     14 
     15 namespace content {
     16 
     17 namespace {
     18 
     19 // The time periods between successive polls of the wifi data.
     20 const int kDefaultPollingIntervalMilliseconds = 10 * 1000;  // 10s
     21 const int kNoChangePollingIntervalMilliseconds = 2 * 60 * 1000;  // 2 mins
     22 const int kTwoNoChangePollingIntervalMilliseconds = 10 * 60 * 1000;  // 10 mins
     23 const int kNoWifiPollingIntervalMilliseconds = 20 * 1000; // 20s
     24 
     25 }  // namespace
     26 
     27 WifiDataProviderChromeOs::WifiDataProviderChromeOs() : started_(false) {
     28 }
     29 
     30 WifiDataProviderChromeOs::~WifiDataProviderChromeOs() {
     31 }
     32 
     33 void WifiDataProviderChromeOs::StartDataProvider() {
     34   DCHECK(CalledOnClientThread());
     35 
     36   DCHECK(polling_policy_ == NULL);
     37   polling_policy_.reset(
     38       new GenericWifiPollingPolicy<kDefaultPollingIntervalMilliseconds,
     39                                    kNoChangePollingIntervalMilliseconds,
     40                                    kTwoNoChangePollingIntervalMilliseconds,
     41                                    kNoWifiPollingIntervalMilliseconds>);
     42 
     43   ScheduleStart();
     44 }
     45 
     46 void WifiDataProviderChromeOs::StopDataProvider() {
     47   DCHECK(CalledOnClientThread());
     48 
     49   polling_policy_.reset();
     50   ScheduleStop();
     51 }
     52 
     53 bool WifiDataProviderChromeOs::GetData(WifiData* data) {
     54   DCHECK(CalledOnClientThread());
     55   DCHECK(data);
     56   *data = wifi_data_;
     57   return is_first_scan_complete_;
     58 }
     59 
     60 void WifiDataProviderChromeOs::DoStartTaskOnUIThread() {
     61   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     62   DoWifiScanTaskOnUIThread();
     63 }
     64 
     65 void WifiDataProviderChromeOs::DoWifiScanTaskOnUIThread() {
     66   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     67 
     68   // This method could be scheduled after a ScheduleStop.
     69   if (!started_)
     70     return;
     71 
     72   WifiData new_data;
     73 
     74   if (GetAccessPointData(&new_data.access_point_data)) {
     75     client_loop()->PostTask(
     76         FROM_HERE,
     77         base::Bind(&WifiDataProviderChromeOs::DidWifiScanTask, this, new_data));
     78   } else {
     79     client_loop()->PostTask(
     80         FROM_HERE,
     81         base::Bind(&WifiDataProviderChromeOs::DidWifiScanTaskNoResults, this));
     82   }
     83 }
     84 
     85 void WifiDataProviderChromeOs::DidWifiScanTaskNoResults() {
     86   DCHECK(CalledOnClientThread());
     87   // Schedule next scan if started (StopDataProvider could have been called
     88   // in between DoWifiScanTaskOnUIThread and this method).
     89   if (started_)
     90     ScheduleNextScan(polling_policy_->NoWifiInterval());
     91 }
     92 
     93 void WifiDataProviderChromeOs::DidWifiScanTask(const WifiData& new_data) {
     94   DCHECK(CalledOnClientThread());
     95   bool update_available = wifi_data_.DiffersSignificantly(new_data);
     96   wifi_data_ = new_data;
     97   // Schedule next scan if started (StopDataProvider could have been called
     98   // in between DoWifiScanTaskOnUIThread and this method).
     99   if (started_) {
    100     polling_policy_->UpdatePollingInterval(update_available);
    101     ScheduleNextScan(polling_policy_->PollingInterval());
    102   }
    103 
    104   if (update_available || !is_first_scan_complete_) {
    105     is_first_scan_complete_ = true;
    106     RunCallbacks();
    107   }
    108 }
    109 
    110 void WifiDataProviderChromeOs::ScheduleNextScan(int interval) {
    111   DCHECK(CalledOnClientThread());
    112   DCHECK(started_);
    113   BrowserThread::PostDelayedTask(
    114       BrowserThread::UI,
    115       FROM_HERE,
    116       base::Bind(&WifiDataProviderChromeOs::DoWifiScanTaskOnUIThread, this),
    117       base::TimeDelta::FromMilliseconds(interval));
    118 }
    119 
    120 void WifiDataProviderChromeOs::ScheduleStop() {
    121   DCHECK(CalledOnClientThread());
    122   DCHECK(started_);
    123   started_ = false;
    124 }
    125 
    126 void WifiDataProviderChromeOs::ScheduleStart() {
    127   DCHECK(CalledOnClientThread());
    128   DCHECK(!started_);
    129   started_ = true;
    130   // Perform first scan ASAP regardless of the polling policy. If this scan
    131   // fails we'll retry at a rate in line with the polling policy.
    132   BrowserThread::PostTask(
    133       BrowserThread::UI,
    134       FROM_HERE,
    135       base::Bind(&WifiDataProviderChromeOs::DoStartTaskOnUIThread, this));
    136 }
    137 
    138 bool WifiDataProviderChromeOs::GetAccessPointData(
    139     WifiData::AccessPointDataSet* result) {
    140   // If wifi isn't enabled, we've effectively completed the task.
    141   // Return true to indicate an empty access point list.
    142   if (!chromeos::NetworkHandler::Get()->geolocation_handler()->wifi_enabled())
    143     return true;
    144 
    145   chromeos::WifiAccessPointVector access_points;
    146   int64 age_ms = 0;
    147   if (!chromeos::NetworkHandler::Get()->geolocation_handler()->
    148       GetWifiAccessPoints(&access_points, &age_ms)) {
    149     return false;
    150   }
    151   for (chromeos::WifiAccessPointVector::const_iterator i
    152            = access_points.begin();
    153        i != access_points.end(); ++i) {
    154     AccessPointData ap_data;
    155     ap_data.mac_address = base::ASCIIToUTF16(i->mac_address);
    156     ap_data.radio_signal_strength = i->signal_strength;
    157     ap_data.channel = i->channel;
    158     ap_data.signal_to_noise = i->signal_to_noise;
    159     ap_data.ssid = base::UTF8ToUTF16(i->ssid);
    160     result->insert(ap_data);
    161   }
    162   // If the age is significantly longer than our long polling time, assume the
    163   // data is stale and return false which will trigger a faster update.
    164   if (age_ms > kTwoNoChangePollingIntervalMilliseconds * 2)
    165     return false;
    166   return true;
    167 }
    168 
    169 // static
    170 WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
    171   return new WifiDataProviderChromeOs();
    172 }
    173 
    174 }  // namespace content
    175