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