Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: chrome/browser/geolocation/wifi_data_provider_linux.cc

Issue 787003: First cut at implementing wifi bindigns for linux, using glib-dbus to Network... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 // WiFi card drivers for Linux implement the Wireless Extensions interface. 5 // Provides wifi scan API binding for suitable for typical linux distributions.
6 // This interface is part of the Linux kernel. 6 // Currently, only the NetworkManager API is used, accessed via D-Bus (in turn
7 // 7 // accessed via the GLib wrapper).
8 // Various sets of tools are available to manipulate the Wireless Extensions, 8
9 // of which Wireless Tools is the default implementation. Wireless Tools 9 #include "chrome/browser/geolocation/wifi_data_provider_linux.h"
10 // provides a C++ library (libiw) as well as a set of command line tools 10
11 // (iwconfig, iwlist etc). See 11 #include <dbus/dbus-glib.h>
12 // http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html for details. 12 #include <glib.h>
13 // 13
14 // Ideally, we would use libiw to obtain WiFi data. However, Wireless Tools is 14 #include "base/scoped_ptr.h"
15 // released under GPL, which is not compatible with Gears. Furthermore, little 15 #include "base/utf_string_conversions.h"
16 // documentation is available for Wireless Extensions, so replicating libiw 16
17 // without copying it directly would be difficult. 17 namespace {
18 // 18 // The time periods between successive polls of the wifi data.
19 // We therefore simply invoke iwlist (one of the Wireless Tools command line 19 const int kDefaultPollingIntervalMilliseconds = 10 * 1000; // 10s
20 // tools) and parse the output. Sample output is shown below. 20 const int kNoChangePollingIntervalMilliseconds = 2 * 60 * 1000; // 2 mins
21 // 21 const int kTwoNoChangePollingIntervalMilliseconds = 10 * 60 * 1000; // 10 mins
22 // lo Interface doesn't support scanning. 22
23 // 23 const char kNetworkManagerServiceName[] = "org.freedesktop.NetworkManager";
24 // ath0 Scan completed : 24 const char kNetworkManagerPath[] = "/org/freedesktop/NetworkManager";
25 // Cell 01 - Address: 00:24:86:11:4C:42 25 const char kNetworkManagerInterface[] = "org.freedesktop.NetworkManager";
26 // ESSID:"Test SSID" 26
27 // Mode:Master 27 // From http://projects.gnome.org/NetworkManager/developers/spec.html
28 // Frequency:2.427 GHz (Channel 4) 28 enum { NM_DEVICE_TYPE_WIFI = 2 };
29 // Quality=5/94 Signal level=-90 dBm Noise level=-95 dBm 29
30 // Encryption key:off 30 // Utility wrappers to make various GLib & DBus structs into scoped objects.
31 // Bit Rates:1 Mb/s; 2 Mb/s; 5 Mb/s; 6 Mb/s; 9 Mb/s 31 class ScopedGPtrArrayFree {
32 // 11 Mb/s; 12 Mb/s; 18 Mb/s 32 public:
33 // Extra:bcn_int=100 33 void operator()(GPtrArray* x) const {
34 // Cell 02 - Address: 00:24:86:11:6F:E2 34 if (x)
35 // ESSID:"Test SSID" 35 g_ptr_array_free(x, TRUE);
36 // Mode:Master 36 }
37 // Frequency:2.447 GHz (Channel 8) 37 };
38 // Quality=4/94 Signal level=-91 dBm Noise level=-95 dBm 38 // Use ScopedGPtrArrayPtr as if it were scoped_ptr<GPtrArray>
39 // Encryption key:off 39 typedef scoped_ptr_malloc<GPtrArray, ScopedGPtrArrayFree> ScopedGPtrArrayPtr;
40 // Bit Rates:1 Mb/s; 2 Mb/s; 5 Mb/s; 6 Mb/s; 9 Mb/s 40
41 // 11 Mb/s; 12 Mb/s; 18 Mb/s 41 class ScopedGObjectFree {
42 // Extra:bcn_int=100 42 public:
43 // 43 void operator()(void* x) const {
44 // TODO(steveblock): Investigate the possibility of the author of Wireless Tools 44 if (x)
45 // releasing libiw under a Gears-compatible license. 45 g_object_unref(x);
46 46 }
47 // TODO(joth): port to chromium 47 };
48 #if 0 48 // Use ScopedDBusGProxyPtr as if it were scoped_ptr<DBusGProxy>
49 49 typedef scoped_ptr_malloc<DBusGProxy, ScopedGObjectFree> ScopedDBusGProxyPtr;
50 #include "gears/geolocation/wifi_data_provider_linux.h" 50
51 51 // Use ScopedGValue::v as an instance of GValue with automatic cleanup.
52 #include <ctype.h> // For isxdigit() 52 class ScopedGValue {
53 #include <stdio.h> 53 public:
54 #include "gears/base/common/string_utils.h" 54 ScopedGValue()
55 #include "gears/geolocation/wifi_data_provider_common.h" 55 : v(empty_gvalue()) {
56 56 }
57 // The time periods, in milliseconds, between successive polls of the wifi data. 57 ~ScopedGValue() {
58 extern const int kDefaultPollingInterval = 10000; // 10s 58 g_value_unset(&v);
59 extern const int kNoChangePollingInterval = 120000; // 2 mins 59 }
60 extern const int kTwoNoChangePollingInterval = 600000; // 10 mins 60 static GValue empty_gvalue() {
61 61 GValue value = {0};
62 // Local function 62 return value;
63 static bool GetAccessPointData(WifiData::AccessPointDataSet *access_points); 63 }
64
65 GValue v;
66 };
67
68 // Wifi API binding to NetworkManager, to allow reuse of the polling behavior
69 // defined in WifiDataProviderCommon.
70 // TODO(joth): NetworkManager also allows for notification based handling,
71 // however this will require reworking of the threading code to run a GLib
72 // event loop (GMainLoop).
73 class NetworkManagerWlanApi : public WifiDataProviderCommon::WlanApiInterface {
74 public:
75 NetworkManagerWlanApi();
76 ~NetworkManagerWlanApi();
77
78 // Must be called before any other interface method. Will return false if the
79 // NetworkManager session cannot be created (e.g. not present on this distro),
80 // in which case no other method may be called.
81 bool Init();
82
83 // WifiDataProviderCommon::WlanApiInterface
84 bool GetAccessPointData(WifiData::AccessPointDataSet* data);
85
86 private:
87 // Checks if the last dbus call returned an error. If it did, logs the error
88 // message, frees it and returns true.
89 // This must be called after every dbus call that accepts |&error_|
90 bool CheckError();
91
92 // Enumerates the list of available network adapter devices known to
93 // NetworkManager. Ownership of the array (and contained objects) is returned
94 // to the caller.
95 GPtrArray* GetAdapterDeviceList();
96
97 // Given the NetworkManager path to a wireless adapater, dumps the wifi scan
98 // results and appends them to |data|. Returns false if a fatal error is
99 // encountered such that the data set could not be populated.
100 bool GetAccessPointsForAdapter(const gchar* adapter_path,
101 WifiData::AccessPointDataSet* data);
102
103 // Internal method used by |GetAccessPointsForAdapter|, given a wifi access
104 // point proxy retrieves the named property into |value_out|. Returns false if
105 // the property could not be read, or is not of type |expected_gvalue_type|.
106 bool GetAccessPointProperty(DBusGProxy* proxy, const char* property_name,
107 int expected_gvalue_type, GValue* value_out);
108
109 // Error from the last dbus call. NULL when there's no error. Freed and
110 // cleared by CheckError().
111 GError* error_;
112 // Connection to the dbus system bus.
113 DBusGConnection* connection_;
114 // Proxy to the network maanger dbus service.
115 ScopedDBusGProxyPtr proxy_;
116
117 DISALLOW_COPY_AND_ASSIGN(NetworkManagerWlanApi);
118 };
119
120 // Convert a wifi frequency to the corresponding channel. Adapted from
121 // geolocaiton/wifilib.cc in googleclient (internal to google).
122 int frquency_in_khz_to_channel(int frequency_khz) {
123 if (frequency_khz >= 2412000 && frequency_khz <= 2472000) // Channels 1-13.
124 return (frequency_khz - 2407000) / 5000;
125 if (frequency_khz == 2484000)
126 return 14;
127 if (frequency_khz > 5000000 && frequency_khz < 6000000) // .11a bands.
128 return (frequency_khz - 5000000) / 5000;
129 // Ignore everything else.
130 return AccessPointData().channel; // invalid channel
131 }
132
133 NetworkManagerWlanApi::NetworkManagerWlanApi()
134 : error_(NULL), connection_(NULL) {
135 }
136
137 NetworkManagerWlanApi::~NetworkManagerWlanApi() {
138 proxy_.reset();
139 if (connection_) {
140 dbus_g_connection_unref(connection_);
141 }
142 DCHECK(!error_) << "Missing a call to CheckError() to clear |error_|";
143 }
144
145 bool NetworkManagerWlanApi::Init() {
146 // Chrome DLL init code handles initializing the thread system, so rather than
147 // get caught up with that nonsense here, lets just assert our requirement.
148 CHECK(g_thread_supported());
149
150 // We should likely do this higher up too, the docs say it must only be done
151 // once but there's no way to know if it already was or not.
152 dbus_g_thread_init();
153
154 // Get a connection to the session bus.
155 connection_ = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error_);
156 if (CheckError())
157 return false;
158 DCHECK(connection_);
159
160 proxy_.reset(dbus_g_proxy_new_for_name(connection_,
161 kNetworkManagerServiceName,
162 kNetworkManagerPath,
163 kNetworkManagerInterface));
164 DCHECK(proxy_.get());
165
166 // Validate the proxy object by checking we can enumerate devices.
167 ScopedGPtrArrayPtr device_list(GetAdapterDeviceList());
168 return !!device_list.get();
169 }
170
171 bool NetworkManagerWlanApi::GetAccessPointData(
172 WifiData::AccessPointDataSet* data) {
173 ScopedGPtrArrayPtr device_list(GetAdapterDeviceList());
174 if (device_list == NULL) {
175 DLOG(WARNING) << "Could not enumerate access points";
176 return false;
177 }
178 int success_count = 0;
179 int fail_count = 0;
180
181 // Iterate the devices, getting APs for each wireless adapter found
182 for (guint i = 0; i < device_list->len; i++) {
183 const gchar* device_path =
184 reinterpret_cast<const gchar*>(g_ptr_array_index(device_list, i));
185
186 ScopedDBusGProxyPtr device_properties_proxy(dbus_g_proxy_new_from_proxy(
187 proxy_.get(), DBUS_INTERFACE_PROPERTIES, device_path));
188 ScopedGValue device_type_g_value;
189 dbus_g_proxy_call(device_properties_proxy.get(), "Get", &error_,
190 G_TYPE_STRING, "org.freedesktop.NetworkManager.Device",
191 G_TYPE_STRING, "DeviceType",
192 G_TYPE_INVALID,
193 G_TYPE_VALUE, &device_type_g_value.v,
194 G_TYPE_INVALID);
195 if (CheckError())
196 continue;
197
198 const guint device_type = g_value_get_uint(&device_type_g_value.v);
199
200 if (device_type == NM_DEVICE_TYPE_WIFI) { // Found a wlan adapter
201 if (GetAccessPointsForAdapter(device_path, data))
202 ++success_count;
203 else
204 ++fail_count;
205 }
206 }
207 // At least one successfull scan overrides any other adapter reporting error.
208 return success_count || fail_count == 0;
209 }
210
211 bool NetworkManagerWlanApi::CheckError() {
212 if (error_) {
213 LOG(ERROR) << "Failed to complete NetworkManager call: " << error_->message;
214 g_error_free(error_);
215 error_ = NULL;
216 return true;
217 }
218 return false;
219 }
220
221 GPtrArray* NetworkManagerWlanApi::GetAdapterDeviceList() {
222 GPtrArray* device_list = NULL;
223 dbus_g_proxy_call(proxy_.get(), "GetDevices", &error_,
224 G_TYPE_INVALID,
225 dbus_g_type_get_collection("GPtrArray",
226 DBUS_TYPE_G_OBJECT_PATH),
227 &device_list,
228 G_TYPE_INVALID);
229 if (CheckError())
230 return NULL;
231 return device_list;
232 }
233
234 bool NetworkManagerWlanApi::GetAccessPointsForAdapter(
235 const gchar* adapter_path, WifiData::AccessPointDataSet* data) {
236 DCHECK(proxy_.get());
237
238 // Create a proxy object for this wifi adapter, and ask it to do a scan
239 // (or at least, dump its scan results).
240 ScopedDBusGProxyPtr wifi_adapter_proxy(dbus_g_proxy_new_from_proxy(
241 proxy_.get(), "org.freedesktop.NetworkManager.Device.Wireless",
242 adapter_path));
243
244 GPtrArray* ap_list_raw = NULL;
245 // Enumerate the access points for this adapter.
246 dbus_g_proxy_call(wifi_adapter_proxy.get(), "GetAccessPoints", &error_,
247 G_TYPE_INVALID,
248 dbus_g_type_get_collection("GPtrArray",
249 DBUS_TYPE_G_OBJECT_PATH),
250 &ap_list_raw,
251 G_TYPE_INVALID);
252 ScopedGPtrArrayPtr ap_list(ap_list_raw); // Takes ownership.
253 ap_list_raw = NULL;
254
255 if (CheckError())
256 return false;
257
258 DLOG(INFO) << "Wireless adapter " << adapter_path << " found "
259 << ap_list->len << " access points.";
260
261 for (guint i = 0; i < ap_list->len; i++) {
262 const gchar* ap_path =
263 reinterpret_cast<const gchar*>(g_ptr_array_index(ap_list, i));
264 ScopedDBusGProxyPtr access_point_proxy(dbus_g_proxy_new_from_proxy(
265 proxy_.get(), DBUS_INTERFACE_PROPERTIES, ap_path));
266
267 AccessPointData access_point_data;
268 { // Read SSID.
269 ScopedGValue ssid_g_value;
270 if (!GetAccessPointProperty(access_point_proxy.get(), "Ssid",
271 G_TYPE_BOXED, &ssid_g_value.v))
272 continue;
273 const GArray* ssid =
274 reinterpret_cast<const GArray*>(g_value_get_boxed(&ssid_g_value.v));
275 UTF8ToUTF16(ssid->data, ssid->len, &access_point_data.ssid);
276 }
277
278 { // Read the mac address
279 ScopedGValue mac_g_value;
280 if (!GetAccessPointProperty(access_point_proxy.get(), "HwAddress",
281 G_TYPE_STRING, &mac_g_value.v))
282 continue;
283 std::string mac = g_value_get_string(&mac_g_value.v);
284 ReplaceSubstringsAfterOffset(&mac, 0U, ":", "");
285 std::vector<uint8> mac_bytes;
286 if (!HexStringToBytes(mac, &mac_bytes) || mac_bytes.size() != 6) {
287 DLOG(WARNING) << "Can't parse mac address (found " << mac_bytes.size()
288 << " bytes) so using raw string: " << mac;
289 access_point_data.mac_address = UTF8ToUTF16(mac);
290 } else {
291 access_point_data.mac_address = MacAddressAsString16(&mac_bytes[0]);
292 }
293 }
294
295 { // Read signal strength.
296 ScopedGValue signal_g_value;
297 if (!GetAccessPointProperty(access_point_proxy.get(), "Strength",
298 G_TYPE_UCHAR, &signal_g_value.v))
299 continue;
300 // Convert strength as a percentage into dBs.
301 access_point_data.radio_signal_strength =
302 -100 + g_value_get_uchar(&signal_g_value.v) / 2;
303 }
304
305 { // Read the channel
306 ScopedGValue freq_g_value;
307 if (!GetAccessPointProperty(access_point_proxy.get(), "Frequency",
308 G_TYPE_UINT, &freq_g_value.v))
309 continue;
310 // NetworkManager returns frequency in MHz.
311 access_point_data.channel =
312 frquency_in_khz_to_channel(g_value_get_uint(&freq_g_value.v) * 1000);
313 }
314 data->insert(access_point_data);
315 }
316 return true;
317 }
318
319 bool NetworkManagerWlanApi::GetAccessPointProperty(DBusGProxy* proxy,
320 const char* property_name,
321 int expected_gvalue_type,
322 GValue* value_out) {
323 dbus_g_proxy_call(proxy, "Get", &error_,
324 G_TYPE_STRING, "org.freedesktop.NetworkManager.AccessPoint",
325 G_TYPE_STRING, property_name,
326 G_TYPE_INVALID,
327 G_TYPE_VALUE, value_out,
328 G_TYPE_INVALID);
329 if (CheckError())
330 return false;
331 if (!G_VALUE_HOLDS(value_out, expected_gvalue_type)) {
332 DLOG(WARNING) << "Property " << property_name << " unexptected type "
333 << G_VALUE_TYPE(value_out);
334 return false;
335 }
336 return true;
337 }
338
339 } // namespace
64 340
65 // static 341 // static
66 template<> 342 template<>
67 WifiDataProviderImplBase *WifiDataProvider::DefaultFactoryFunction() { 343 WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
68 return new LinuxWifiDataProvider(); 344 return new WifiDataProviderLinux();
69 } 345 }
70 346
71 347 WifiDataProviderLinux::WifiDataProviderLinux() {
72 LinuxWifiDataProvider::LinuxWifiDataProvider() 348 }
73 : is_first_scan_complete_(false) { 349
74 Start(); 350 WifiDataProviderLinux::~WifiDataProviderLinux() {
75 } 351 }
76 352
77 LinuxWifiDataProvider::~LinuxWifiDataProvider() { 353 WifiDataProviderCommon::WlanApiInterface*
78 stop_event_.Signal(); 354 WifiDataProviderLinux::NewWlanApi() {
79 Join(); 355 scoped_ptr<NetworkManagerWlanApi> wlan_api(new NetworkManagerWlanApi);
80 } 356 if (wlan_api->Init())
81 357 return wlan_api.release();
82 bool LinuxWifiDataProvider::GetData(WifiData *data) { 358 return NULL;
83 DCHECK(data); 359 }
84 MutexLock lock(&data_mutex_); 360
85 *data = wifi_data_; 361 PollingPolicyInterface* WifiDataProviderLinux::NewPollingPolicy() {
86 // If we've successfully completed a scan, indicate that we have all of the 362 return new GenericPollingPolicy<kDefaultPollingIntervalMilliseconds,
87 // data we can get. 363 kNoChangePollingIntervalMilliseconds,
88 return is_first_scan_complete_; 364 kTwoNoChangePollingIntervalMilliseconds>;
89 } 365 }
90 366
91 // Thread implementation
92 void LinuxWifiDataProvider::Run() {
93 // Regularly get the access point data.
94 int polling_interval = kDefaultPollingInterval;
95 do {
96 WifiData new_data;
97 if (GetAccessPointData(&new_data.access_point_data)) {
98 bool update_available;
99 data_mutex_.Lock();
100 update_available = wifi_data_.DiffersSignificantly(new_data);
101 wifi_data_ = new_data;
102 data_mutex_.Unlock();
103 polling_interval =
104 UpdatePollingInterval(polling_interval, update_available);
105 if (update_available) {
106 is_first_scan_complete_ = true;
107 NotifyListeners();
108 }
109 }
110 } while (!stop_event_.WaitWithTimeout(polling_interval));
111 }
112
113 // Local functions
114
115 static bool IsValidMacAddress(const char *mac_address) {
116 return isxdigit(mac_address[0]) &&
117 isxdigit(mac_address[1]) &&
118 mac_address[2] == ':' &&
119 isxdigit(mac_address[3]) &&
120 isxdigit(mac_address[4]) &&
121 mac_address[5] == ':' &&
122 isxdigit(mac_address[6]) &&
123 isxdigit(mac_address[7]) &&
124 mac_address[8] == ':' &&
125 isxdigit(mac_address[9]) &&
126 isxdigit(mac_address[10]) &&
127 mac_address[11] == ':' &&
128 isxdigit(mac_address[12]) &&
129 isxdigit(mac_address[13]) &&
130 mac_address[14] == ':' &&
131 isxdigit(mac_address[15]) &&
132 isxdigit(mac_address[16]);
133 }
134
135 static void ParseLine(const std::string &line,
136 const std::string &mac_address_string,
137 const std::string &ssid_string,
138 const std::string &signal_strength_string,
139 AccessPointData *access_point_data) {
140 // Currently we get only MAC address, SSID and signal strength.
141 // TODO(steveblock): Work out how to get age, channel and signal-to-noise.
142 std::string::size_type index;
143 if ((index = line.find(mac_address_string)) != std::string::npos) {
144 // MAC address
145 if (IsValidMacAddress(&line.at(index + mac_address_string.size()))) {
146 UTF8ToString16(&line.at(index + mac_address_string.size()),
147 17, // XX:XX:XX:XX:XX:XX
148 &access_point_data->mac_address);
149 }
150 } else if ((index = line.find(ssid_string)) != std::string::npos) {
151 // SSID
152 // The string should be quoted.
153 std::string::size_type start = index + ssid_string.size() + 1;
154 std::string::size_type end = line.find('\"', start);
155 // If we can't find a trailing quote, something has gone wrong.
156 if (end != std::string::npos) {
157 UTF8ToString16(&line.at(start), end - start, &access_point_data->ssid);
158 }
159 } else if ((index = line.find(signal_strength_string)) != std::string::npos) {
160 // Signal strength
161 // iwlist will convert to dBm if it can. If it has failed to do so, we can't
162 // make use of the data.
163 if (line.find("dBm") != std::string::npos) {
164 // atoi will ignore trailing non-numeric characters
165 access_point_data->radio_signal_strength =
166 atoi(&line.at(index + signal_strength_string.size()));
167 }
168 }
169 }
170
171 static void ParseAccessPoint(const std::string &text,
172 const std::string &mac_address_string,
173 const std::string &ssid_string,
174 const std::string &signal_strength_string,
175 AccessPointData *access_point_data) {
176 // Split response into lines to aid parsing.
177 std::string::size_type start = 0;
178 std::string::size_type end;
179 do {
180 end = text.find('\n', start);
181 std::string::size_type length = (end == std::string::npos) ?
182 std::string::npos : end - start;
183 ParseLine(text.substr(start, length),
184 mac_address_string,
185 ssid_string,
186 signal_strength_string,
187 access_point_data);
188 start = end + 1;
189 } while (end != std::string::npos);
190 }
191
192 // Issues the specified command, and parses the response. Data for each access
193 // point is separated by the given delimiter. Within each block of data, the
194 // repsonse is split into lines and data is extracted by searching for the MAC
195 // address, SSID and signal strength strings.
196 bool IssueCommandAndParseResult(const char *command,
197 const char *delimiter,
198 const std::string &mac_address_string,
199 const std::string &ssid_string,
200 const std::string &signal_strength_string,
201 WifiData::AccessPointDataSet *access_points) {
202 // Open pipe in read mode.
203 FILE *result_pipe = popen(command, "r");
204 if (result_pipe == NULL) {
205 LOG(("IssueCommand(): Failed to open pipe.\n"));
206 return false;
207 }
208
209 // Read results of command.
210 static const int kBufferSize = 1024;
211 char buffer[kBufferSize];
212 size_t bytes_read;
213 std::string result;
214 do {
215 bytes_read = fread(buffer, 1, kBufferSize, result_pipe);
216 result.append(buffer, bytes_read);
217 } while (static_cast<int>(bytes_read) == kBufferSize);
218 pclose(result_pipe);
219
220
221 // Parse results.
222 DCHECK(access_points);
223 access_points->clear();
224 std::string::size_type start = result.find(delimiter);
225 while (start != std::string::npos) {
226 std::string::size_type end = result.find(delimiter, start + 1);
227 std::string::size_type length = (end == std::string::npos) ?
228 std::string::npos : end - start;
229 AccessPointData access_point_data;
230 ParseAccessPoint(result.substr(start, length),
231 mac_address_string,
232 ssid_string,
233 signal_strength_string,
234 &access_point_data);
235 access_points->insert(access_point_data);
236 start = end;
237 }
238
239 return !access_points->empty();
240 }
241
242 static bool GetAccessPointData(WifiData::AccessPointDataSet *access_points) {
243 return IssueCommandAndParseResult("iwlist scan 2> /dev/null",
244 "Cell ",
245 "Address: ",
246 "ESSID:",
247 "Signal level=",
248 access_points) ||
249 IssueCommandAndParseResult("iwconfig 2> /dev/null",
250 "ESSID:\"",
251 "Access Point: ",
252 "ESSID:",
253 "Signal level=",
254 access_points);
255 }
256
257 #endif // 0
OLDNEW
« no previous file with comments | « chrome/browser/geolocation/wifi_data_provider_linux.h ('k') | chrome/browser/geolocation/wifi_data_provider_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698