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

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

Issue 7725001: Rework wifi_data_provider_linux.cc with our D-Bus library. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 9 years, 3 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // Provides wifi scan API binding for suitable for typical linux distributions. 5 // Provides wifi scan API binding for suitable for typical linux distributions.
6 // Currently, only the NetworkManager API is used, accessed via D-Bus (in turn 6 // Currently, only the NetworkManager API is used, accessed via D-Bus (in turn
7 // accessed via the GLib wrapper). 7 // accessed via the GLib wrapper).
8 8
9 #include "content/browser/geolocation/wifi_data_provider_linux.h" 9 #include "content/browser/geolocation/wifi_data_provider_linux.h"
10 10
11 #include <dbus/dbus-glib.h>
12 #include <dbus/dbus-glib-lowlevel.h>
13 #include <dbus/dbus.h>
14 #include <dlfcn.h>
15 #include <glib.h>
16
17 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
18 #include "base/string_number_conversions.h" 12 #include "base/string_number_conversions.h"
19 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
14 #include "dbus/bus.h"
15 #include "dbus/message.h"
16 #include "dbus/object_proxy.h"
20 17
21 namespace { 18 namespace {
22 // The time periods between successive polls of the wifi data. 19 // The time periods between successive polls of the wifi data.
23 const int kDefaultPollingIntervalMilliseconds = 10 * 1000; // 10s 20 const int kDefaultPollingIntervalMilliseconds = 10 * 1000; // 10s
24 const int kNoChangePollingIntervalMilliseconds = 2 * 60 * 1000; // 2 mins 21 const int kNoChangePollingIntervalMilliseconds = 2 * 60 * 1000; // 2 mins
25 const int kTwoNoChangePollingIntervalMilliseconds = 10 * 60 * 1000; // 10 mins 22 const int kTwoNoChangePollingIntervalMilliseconds = 10 * 60 * 1000; // 10 mins
26 const int kNoWifiPollingIntervalMilliseconds = 20 * 1000; // 20s 23 const int kNoWifiPollingIntervalMilliseconds = 20 * 1000; // 20s
27 24
28 const char kNetworkManagerServiceName[] = "org.freedesktop.NetworkManager"; 25 const char kNetworkManagerServiceName[] = "org.freedesktop.NetworkManager";
29 const char kNetworkManagerPath[] = "/org/freedesktop/NetworkManager"; 26 const char kNetworkManagerPath[] = "/org/freedesktop/NetworkManager";
30 const char kNetworkManagerInterface[] = "org.freedesktop.NetworkManager"; 27 const char kNetworkManagerInterface[] = "org.freedesktop.NetworkManager";
31 28
32 // From http://projects.gnome.org/NetworkManager/developers/spec.html 29 // From http://projects.gnome.org/NetworkManager/developers/spec.html
33 enum { NM_DEVICE_TYPE_WIFI = 2 }; 30 enum { NM_DEVICE_TYPE_WIFI = 2 };
34 31
35 // Function type matching dbus_g_bus_get_private so that we can
36 // dynamically determine the presence of this symbol (see
37 // NetworkManagerWlanApi::Init)
38 typedef DBusGConnection* DBusGBusGetPrivateFunc(
39 DBusBusType type, GMainContext* context, GError** error);
40
41 // Utility wrappers to make various GLib & DBus structs into scoped objects.
42 class ScopedGPtrArrayFree {
43 public:
44 void operator()(GPtrArray* x) const {
45 if (x)
46 g_ptr_array_free(x, TRUE);
47 }
48 };
49 // Use ScopedGPtrArrayPtr as if it were scoped_ptr<GPtrArray>
50 typedef scoped_ptr_malloc<GPtrArray, ScopedGPtrArrayFree> ScopedGPtrArrayPtr;
51
52 class ScopedGObjectFree {
53 public:
54 void operator()(void* x) const {
55 if (x)
56 g_object_unref(x);
57 }
58 };
59 // Use ScopedDBusGProxyPtr as if it were scoped_ptr<DBusGProxy>
60 typedef scoped_ptr_malloc<DBusGProxy, ScopedGObjectFree> ScopedDBusGProxyPtr;
61
62 // Use ScopedGValue::v as an instance of GValue with automatic cleanup.
63 class ScopedGValue {
64 public:
65 ScopedGValue()
66 : v(empty_gvalue()) {
67 }
68 ~ScopedGValue() {
69 g_value_unset(&v);
70 }
71 static GValue empty_gvalue() {
72 GValue value = {0};
73 return value;
74 }
75
76 GValue v;
77 };
78
79 // Use ScopedDLHandle to automatically clean up after dlopen.
80 class ScopedDLHandle {
81 public:
82 ScopedDLHandle(void* handle)
83 : handle_(handle) {
84 }
85 ~ScopedDLHandle() {
86 if (handle_)
87 dlclose(handle_);
88 }
89 void* get() {
90 return handle_;
91 }
92 private:
93 void *handle_;
94 };
95
96 // Wifi API binding to NetworkManager, to allow reuse of the polling behavior 32 // Wifi API binding to NetworkManager, to allow reuse of the polling behavior
97 // defined in WifiDataProviderCommon. 33 // defined in WifiDataProviderCommon.
98 // TODO(joth): NetworkManager also allows for notification based handling, 34 // TODO(joth): NetworkManager also allows for notification based handling,
99 // however this will require reworking of the threading code to run a GLib 35 // however this will require reworking of the threading code to run a GLib
100 // event loop (GMainLoop). 36 // event loop (GMainLoop).
101 class NetworkManagerWlanApi : public WifiDataProviderCommon::WlanApiInterface { 37 class NetworkManagerWlanApi : public WifiDataProviderCommon::WlanApiInterface {
102 public: 38 public:
103 NetworkManagerWlanApi(); 39 NetworkManagerWlanApi();
104 ~NetworkManagerWlanApi(); 40 ~NetworkManagerWlanApi();
105 41
106 // Must be called before any other interface method. Will return false if the 42 // Must be called before any other interface method. Will return false if the
107 // NetworkManager session cannot be created (e.g. not present on this distro), 43 // NetworkManager session cannot be created (e.g. not present on this distro),
108 // in which case no other method may be called. 44 // in which case no other method may be called.
109 bool Init(); 45 bool Init();
110 46
47 // Similar to Init() but can inject the bus object. Used for testing.
48 bool InitWithBus(dbus::Bus* bus);
49
111 // WifiDataProviderCommon::WlanApiInterface 50 // WifiDataProviderCommon::WlanApiInterface
112 bool GetAccessPointData(WifiData::AccessPointDataSet* data); 51 //
52 // This function makes blocking D-Bus calls, but it's totally fine as
53 // the code runs in "Geolocation" thread, not the browser's UI thread.
54 virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data);
113 55
114 private: 56 private:
115 // Checks if the last dbus call returned an error. If it did, logs the error
116 // message, frees it and returns true.
117 // This must be called after every dbus call that accepts |&error_|
118 bool CheckError();
119
120 // Enumerates the list of available network adapter devices known to 57 // Enumerates the list of available network adapter devices known to
121 // NetworkManager. Ownership of the array (and contained objects) is returned 58 // NetworkManager. Return true on success.
122 // to the caller. 59 bool GetAdapterDeviceList(std::vector<std::string>* device_paths);
123 GPtrArray* GetAdapterDeviceList();
124 60
125 // Given the NetworkManager path to a wireless adapater, dumps the wifi scan 61 // Given the NetworkManager path to a wireless adapater, dumps the wifi scan
126 // results and appends them to |data|. Returns false if a fatal error is 62 // results and appends them to |data|. Returns false if a fatal error is
127 // encountered such that the data set could not be populated. 63 // encountered such that the data set could not be populated.
128 bool GetAccessPointsForAdapter(const gchar* adapter_path, 64 bool GetAccessPointsForAdapter(const std::string& adapter_path,
129 WifiData::AccessPointDataSet* data); 65 WifiData::AccessPointDataSet* data);
130 66
131 // Internal method used by |GetAccessPointsForAdapter|, given a wifi access 67 // Internal method used by |GetAccessPointsForAdapter|, given a wifi access
132 // point proxy retrieves the named property into |value_out|. Returns false if 68 // point proxy retrieves the named property and returns it. Returns NULL if
133 // the property could not be read, or is not of type |expected_gvalue_type|. 69 // the property could not be read.
134 bool GetAccessPointProperty(DBusGProxy* proxy, const char* property_name, 70 dbus::Response* GetAccessPointProperty(dbus::ObjectProxy* proxy,
135 int expected_gvalue_type, GValue* value_out); 71 const std::string& property_name);
136 72
137 // Error from the last dbus call. NULL when there's no error. Freed and 73 scoped_refptr<dbus::Bus> system_bus_;
138 // cleared by CheckError(). 74 dbus::ObjectProxy* network_manager_proxy_;
139 GError* error_;
140 // Connection to the dbus system bus.
141 DBusGConnection* connection_;
142 // Main context
143 GMainContext* context_;
144 // Proxy to the network manager dbus service.
145 ScopedDBusGProxyPtr proxy_;
146 75
147 DISALLOW_COPY_AND_ASSIGN(NetworkManagerWlanApi); 76 DISALLOW_COPY_AND_ASSIGN(NetworkManagerWlanApi);
148 }; 77 };
149 78
150 // Convert a wifi frequency to the corresponding channel. Adapted from 79 // Convert a wifi frequency to the corresponding channel. Adapted from
151 // geolocaiton/wifilib.cc in googleclient (internal to google). 80 // geolocaiton/wifilib.cc in googleclient (internal to google).
152 int frquency_in_khz_to_channel(int frequency_khz) { 81 int frquency_in_khz_to_channel(int frequency_khz) {
153 if (frequency_khz >= 2412000 && frequency_khz <= 2472000) // Channels 1-13. 82 if (frequency_khz >= 2412000 && frequency_khz <= 2472000) // Channels 1-13.
154 return (frequency_khz - 2407000) / 5000; 83 return (frequency_khz - 2407000) / 5000;
155 if (frequency_khz == 2484000) 84 if (frequency_khz == 2484000)
156 return 14; 85 return 14;
157 if (frequency_khz > 5000000 && frequency_khz < 6000000) // .11a bands. 86 if (frequency_khz > 5000000 && frequency_khz < 6000000) // .11a bands.
158 return (frequency_khz - 5000000) / 5000; 87 return (frequency_khz - 5000000) / 5000;
159 // Ignore everything else. 88 // Ignore everything else.
160 return AccessPointData().channel; // invalid channel 89 return AccessPointData().channel; // invalid channel
161 } 90 }
162 91
163 NetworkManagerWlanApi::NetworkManagerWlanApi() 92 NetworkManagerWlanApi::NetworkManagerWlanApi() {
bulach 2011/08/25 13:22:45 not strictly needed, but maybe zero-initialize net
satorux1 2011/08/25 17:00:17 Good catch! Done.
164 : error_(NULL),
165 connection_(NULL),
166 context_(NULL)
167 {
168 } 93 }
169 94
170 NetworkManagerWlanApi::~NetworkManagerWlanApi() { 95 NetworkManagerWlanApi::~NetworkManagerWlanApi() {
171 proxy_.reset();
172 if (connection_) {
173 dbus_connection_close(dbus_g_connection_get_connection(connection_));
174 dbus_g_connection_unref(connection_);
175 }
176 if (context_)
177 g_main_context_unref(context_);
178
179 DCHECK(!error_) << "Missing a call to CheckError() to clear |error_|";
180 } 96 }
181 97
182 bool NetworkManagerWlanApi::Init() { 98 bool NetworkManagerWlanApi::Init() {
183 // Chrome DLL init code handles initializing the thread system, so rather than 99 dbus::Bus::Options options;
184 // get caught up with that nonsense here, lets just assert our requirement. 100 options.bus_type = dbus::Bus::SYSTEM;
185 CHECK(g_thread_supported()); 101 options.connection_type = dbus::Bus::PRIVATE;
102 return InitWithBus(new dbus::Bus(options));
103 }
186 104
187 // We require a private bus to ensure that we don't interfere with the 105 bool NetworkManagerWlanApi::InitWithBus(dbus::Bus* bus) {
188 // default loop on the main thread. Unforunately this functionality is only 106 system_bus_ = bus;
189 // available in dbus-glib-0.84 and later. We do a dynamic symbol lookup 107 // system_bus_ will own all object proxies created from the bus.
190 // to determine if dbus_g_bus_get_private is available. See bug 108 network_manager_proxy_ =
191 // http://code.google.com/p/chromium/issues/detail?id=59913 for more 109 system_bus_->GetObjectProxy(kNetworkManagerServiceName,
192 // information. 110 kNetworkManagerPath);
193 ScopedDLHandle handle(dlopen(NULL, RTLD_LAZY));
194 if (!handle.get())
195 return false;
196
197 DBusGBusGetPrivateFunc *my_dbus_g_bus_get_private =
198 (DBusGBusGetPrivateFunc *) dlsym(handle.get(), "dbus_g_bus_get_private");
199
200 if (!my_dbus_g_bus_get_private) {
201 LOG(ERROR) << "We need dbus-glib >= 0.84 for wifi geolocation.";
202 return false;
203 }
204 // Get a private connection to the session bus.
205 context_ = g_main_context_new();
206 DCHECK(context_);
207 connection_ = my_dbus_g_bus_get_private(DBUS_BUS_SYSTEM, context_, &error_);
208
209 if (CheckError())
210 return false;
211 DCHECK(connection_);
212
213 // Disable timers on the connection since we don't need them and
214 // we're not going to run them anyway as the connection is associated
215 // with a private context. See bug http://crbug.com/40803
216 dbus_bool_t ok = dbus_connection_set_timeout_functions(
217 dbus_g_connection_get_connection(connection_),
218 NULL, NULL, NULL, NULL, NULL);
219 DCHECK(ok);
220
221 proxy_.reset(dbus_g_proxy_new_for_name(connection_,
222 kNetworkManagerServiceName,
223 kNetworkManagerPath,
224 kNetworkManagerInterface));
225 DCHECK(proxy_.get());
226
227 // Validate the proxy object by checking we can enumerate devices. 111 // Validate the proxy object by checking we can enumerate devices.
228 ScopedGPtrArrayPtr device_list(GetAdapterDeviceList()); 112 std::vector<std::string> adapter_paths;
229 return !!device_list.get(); 113 const bool success = GetAdapterDeviceList(&adapter_paths);
114 VLOG(1) << "Init() result: " << success;
115 return success;
230 } 116 }
231 117
232 bool NetworkManagerWlanApi::GetAccessPointData( 118 bool NetworkManagerWlanApi::GetAccessPointData(
233 WifiData::AccessPointDataSet* data) { 119 WifiData::AccessPointDataSet* data) {
234 ScopedGPtrArrayPtr device_list(GetAdapterDeviceList()); 120 std::vector<std::string> device_paths;
235 if (device_list == NULL) { 121 if (!GetAdapterDeviceList(&device_paths)) {
236 DLOG(WARNING) << "Could not enumerate access points"; 122 LOG(WARNING) << "Could not enumerate access points";
237 return false; 123 return false;
238 } 124 }
239 int success_count = 0; 125 int success_count = 0;
240 int fail_count = 0; 126 int fail_count = 0;
241 127
242 // Iterate the devices, getting APs for each wireless adapter found 128 // Iterate the devices, getting APs for each wireless adapter found
243 for (guint i = 0; i < device_list->len; i++) { 129 for (size_t i = 0; i < device_paths.size(); ++i) {
244 const gchar* device_path = 130 const std::string& device_path = device_paths[i];
245 reinterpret_cast<const gchar*>(g_ptr_array_index(device_list, i)); 131 VLOG(1) << "Checking device: " << device_path;
246 132
247 ScopedDBusGProxyPtr device_properties_proxy(dbus_g_proxy_new_from_proxy( 133 dbus::ObjectProxy* device_proxy =
248 proxy_.get(), DBUS_INTERFACE_PROPERTIES, device_path)); 134 system_bus_->GetObjectProxy(kNetworkManagerServiceName,
249 ScopedGValue device_type_g_value; 135 device_path);
250 dbus_g_proxy_call(device_properties_proxy.get(), "Get", &error_,
251 G_TYPE_STRING, "org.freedesktop.NetworkManager.Device",
252 G_TYPE_STRING, "DeviceType",
253 G_TYPE_INVALID,
254 G_TYPE_VALUE, &device_type_g_value.v,
255 G_TYPE_INVALID);
256 if (CheckError())
257 continue;
258 136
259 const guint device_type = g_value_get_uint(&device_type_g_value.v); 137 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, "Get");
138 dbus::MessageWriter builder(&method_call);
139 builder.AppendString("org.freedesktop.NetworkManager.Device");
140 builder.AppendString("DeviceType");
141 scoped_ptr<dbus::Response> response(
142 device_proxy->CallMethodAndBlock(
143 &method_call,
144 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
145 if (!response.get()) {
146 LOG(WARNING) << "Failed to get the device type for " << device_path;
147 continue; // Check the next device.
148 }
149 dbus::MessageReader reader(response.get());
150 uint32 device_type = 0;
151 if (!reader.PopVariantOfUint32(&device_type)) {
152 LOG(WARNING) << "Unexpected response for " << device_type << ": "
153 << response->ToString();
154 continue; // Check the next device.
155 }
156 VLOG(1) << "Device type: " << device_type;
260 157
261 if (device_type == NM_DEVICE_TYPE_WIFI) { // Found a wlan adapter 158 if (device_type == NM_DEVICE_TYPE_WIFI) { // Found a wlan adapter
262 if (GetAccessPointsForAdapter(device_path, data)) 159 if (GetAccessPointsForAdapter(device_path, data))
263 ++success_count; 160 ++success_count;
264 else 161 else
265 ++fail_count; 162 ++fail_count;
266 } 163 }
267 } 164 }
268 // At least one successfull scan overrides any other adapter reporting error. 165 // At least one successfull scan overrides any other adapter reporting error.
269 return success_count || fail_count == 0; 166 return success_count || fail_count == 0;
270 } 167 }
271 168
272 bool NetworkManagerWlanApi::CheckError() { 169 bool NetworkManagerWlanApi::GetAdapterDeviceList(
273 if (error_) { 170 std::vector<std::string>* device_paths) {
274 LOG(ERROR) << "Failed to complete NetworkManager call: " << error_->message; 171 dbus::MethodCall method_call(kNetworkManagerInterface, "GetDevices");
275 g_error_free(error_); 172 scoped_ptr<dbus::Response> response(
276 error_ = NULL; 173 network_manager_proxy_->CallMethodAndBlock(
277 return true; 174 &method_call,
175 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
176 if (!response.get()) {
177 LOG(WARNING) << "Failed to get the device list";
178 return false;
278 } 179 }
279 return false; 180
181 dbus::MessageReader reader(response.get());
182 if (!reader.PopArrayOfObjectPaths(device_paths)) {
183 LOG(WARNING) << "Unexpected response: " << response->ToString();
184 return false;
185 }
186 return true;
280 } 187 }
281 188
282 GPtrArray* NetworkManagerWlanApi::GetAdapterDeviceList() {
283 GPtrArray* device_list = NULL;
284 dbus_g_proxy_call(proxy_.get(), "GetDevices", &error_,
285 G_TYPE_INVALID,
286 dbus_g_type_get_collection("GPtrArray",
287 DBUS_TYPE_G_OBJECT_PATH),
288 &device_list,
289 G_TYPE_INVALID);
290 if (CheckError())
291 return NULL;
292 return device_list;
293 }
294 189
295 bool NetworkManagerWlanApi::GetAccessPointsForAdapter( 190 bool NetworkManagerWlanApi::GetAccessPointsForAdapter(
296 const gchar* adapter_path, WifiData::AccessPointDataSet* data) { 191 const std::string& adapter_path, WifiData::AccessPointDataSet* data) {
297 DCHECK(proxy_.get());
298
299 // Create a proxy object for this wifi adapter, and ask it to do a scan 192 // Create a proxy object for this wifi adapter, and ask it to do a scan
300 // (or at least, dump its scan results). 193 // (or at least, dump its scan results).
301 ScopedDBusGProxyPtr wifi_adapter_proxy(dbus_g_proxy_new_from_proxy( 194 dbus::ObjectProxy* device_proxy =
302 proxy_.get(), "org.freedesktop.NetworkManager.Device.Wireless", 195 system_bus_->GetObjectProxy(kNetworkManagerServiceName,
303 adapter_path)); 196 adapter_path);
197 dbus::MethodCall method_call(
198 "org.freedesktop.NetworkManager.Device.Wireless",
199 "GetAccessPoints");
200 scoped_ptr<dbus::Response> response(
201 device_proxy->CallMethodAndBlock(
202 &method_call,
203 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
204 if (!response.get()) {
205 LOG(WARNING) << "Failed to get access points data for " << adapter_path;
206 return false;
207 }
208 dbus::MessageReader reader(response.get());
209 std::vector<std::string> access_point_paths;
210 if (!reader.PopArrayOfObjectPaths(&access_point_paths)) {
211 LOG(WARNING) << "Unexpected response for " << adapter_path << ": "
212 << response->ToString();
213 return false;
214 }
304 215
305 GPtrArray* ap_list_raw = NULL; 216 VLOG(1) << "Wireless adapter " << adapter_path << " found "
306 // Enumerate the access points for this adapter. 217 << access_point_paths.size() << " access points.";
307 dbus_g_proxy_call(wifi_adapter_proxy.get(), "GetAccessPoints", &error_,
308 G_TYPE_INVALID,
309 dbus_g_type_get_collection("GPtrArray",
310 DBUS_TYPE_G_OBJECT_PATH),
311 &ap_list_raw,
312 G_TYPE_INVALID);
313 ScopedGPtrArrayPtr ap_list(ap_list_raw); // Takes ownership.
314 ap_list_raw = NULL;
315 218
316 if (CheckError()) 219 for (size_t i = 0; i < access_point_paths.size(); ++i) {
317 return false; 220 const std::string& access_point_path = access_point_paths[i];
221 VLOG(1) << "Checking access point: " << access_point_path;
318 222
319 DVLOG(1) << "Wireless adapter " << adapter_path << " found " << ap_list->len 223 dbus::ObjectProxy* access_point_proxy =
320 << " access points."; 224 system_bus_->GetObjectProxy(kNetworkManagerServiceName,
321 225 access_point_path);
322 for (guint i = 0; i < ap_list->len; i++) {
323 const gchar* ap_path =
324 reinterpret_cast<const gchar*>(g_ptr_array_index(ap_list, i));
325 ScopedDBusGProxyPtr access_point_proxy(dbus_g_proxy_new_from_proxy(
326 proxy_.get(), DBUS_INTERFACE_PROPERTIES, ap_path));
327 226
328 AccessPointData access_point_data; 227 AccessPointData access_point_data;
329 { // Read SSID. 228 {
330 ScopedGValue ssid_g_value; 229 scoped_ptr<dbus::Response> response(
331 if (!GetAccessPointProperty(access_point_proxy.get(), "Ssid", 230 GetAccessPointProperty(access_point_proxy, "Ssid"));
332 G_TYPE_BOXED, &ssid_g_value.v)) 231 if (!response.get())
333 continue; 232 continue;
334 const GArray* ssid = 233 // The response should contain a variant that contains an array of bytes.
335 reinterpret_cast<const GArray*>(g_value_get_boxed(&ssid_g_value.v)); 234 dbus::MessageReader reader(response.get());
336 UTF8ToUTF16(ssid->data, ssid->len, &access_point_data.ssid); 235 dbus::MessageReader variant_reader(response.get());
236 if (!reader.PopVariant(&variant_reader)) {
237 LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
238 << response->ToString();
239 continue;
240 }
241 uint8* ssid_bytes = NULL;
242 size_t ssid_length = 0;
243 if (!variant_reader.PopArrayOfBytes(&ssid_bytes, &ssid_length)) {
244 LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
245 << response->ToString();
246 continue;
247 }
248 std::string ssid(ssid_bytes, ssid_bytes + ssid_length);
249 access_point_data.ssid = UTF8ToUTF16(ssid);
337 } 250 }
338 251
339 { // Read the mac address 252 { // Read the mac address
340 ScopedGValue mac_g_value; 253 scoped_ptr<dbus::Response> response(
341 if (!GetAccessPointProperty(access_point_proxy.get(), "HwAddress", 254 GetAccessPointProperty(access_point_proxy, "HwAddress"));
342 G_TYPE_STRING, &mac_g_value.v)) 255 if (!response.get())
343 continue; 256 continue;
344 std::string mac = g_value_get_string(&mac_g_value.v); 257 dbus::MessageReader reader(response.get());
258 std::string mac;
259 if (!reader.PopVariantOfString(&mac)) {
260 LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
261 << response->ToString();
262 continue;
263 }
264
345 ReplaceSubstringsAfterOffset(&mac, 0U, ":", ""); 265 ReplaceSubstringsAfterOffset(&mac, 0U, ":", "");
346 std::vector<uint8> mac_bytes; 266 std::vector<uint8> mac_bytes;
347 if (!base::HexStringToBytes(mac, &mac_bytes) || mac_bytes.size() != 6) { 267 if (!base::HexStringToBytes(mac, &mac_bytes) || mac_bytes.size() != 6) {
348 DLOG(WARNING) << "Can't parse mac address (found " << mac_bytes.size() 268 LOG(WARNING) << "Can't parse mac address (found " << mac_bytes.size()
349 << " bytes) so using raw string: " << mac; 269 << " bytes) so using raw string: " << mac;
350 access_point_data.mac_address = UTF8ToUTF16(mac); 270 access_point_data.mac_address = UTF8ToUTF16(mac);
351 } else { 271 } else {
352 access_point_data.mac_address = MacAddressAsString16(&mac_bytes[0]); 272 access_point_data.mac_address = MacAddressAsString16(&mac_bytes[0]);
353 } 273 }
354 } 274 }
355 275
356 { // Read signal strength. 276 { // Read signal strength.
357 ScopedGValue signal_g_value; 277 scoped_ptr<dbus::Response> response(
358 if (!GetAccessPointProperty(access_point_proxy.get(), "Strength", 278 GetAccessPointProperty(access_point_proxy, "Strength"));
359 G_TYPE_UCHAR, &signal_g_value.v)) 279 if (!response.get())
360 continue; 280 continue;
281 dbus::MessageReader reader(response.get());
282 uint8 strength = 0;
283 if (!reader.PopVariantOfByte(&strength)) {
284 LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
285 << response->ToString();
286 continue;
287 }
361 // Convert strength as a percentage into dBs. 288 // Convert strength as a percentage into dBs.
362 access_point_data.radio_signal_strength = 289 access_point_data.radio_signal_strength = -100 + strength / 2;
363 -100 + g_value_get_uchar(&signal_g_value.v) / 2;
364 } 290 }
365 291
366 { // Read the channel 292 { // Read the channel
367 ScopedGValue freq_g_value; 293 scoped_ptr<dbus::Response> response(
368 if (!GetAccessPointProperty(access_point_proxy.get(), "Frequency", 294 GetAccessPointProperty(access_point_proxy, "Frequency"));
369 G_TYPE_UINT, &freq_g_value.v)) 295 if (!response.get())
370 continue; 296 continue;
297 dbus::MessageReader reader(response.get());
298 uint32 frequency = 0;
299 if (!reader.PopVariantOfUint32(&frequency)) {
300 LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
301 << response->ToString();
302 continue;
303 }
304
371 // NetworkManager returns frequency in MHz. 305 // NetworkManager returns frequency in MHz.
372 access_point_data.channel = 306 access_point_data.channel =
373 frquency_in_khz_to_channel(g_value_get_uint(&freq_g_value.v) * 1000); 307 frquency_in_khz_to_channel(frequency * 1000);
374 } 308 }
309 VLOG(1) << "Access point data of " << access_point_path << ": "
310 << "SSID: " << access_point_data.ssid << ", "
311 << "MAC: " << access_point_data.mac_address << ", "
312 << "Strength: " << access_point_data.radio_signal_strength << ", "
313 << "Channel: " << access_point_data.channel;
314
375 data->insert(access_point_data); 315 data->insert(access_point_data);
376 } 316 }
377 return true; 317 return true;
378 } 318 }
379 319
380 bool NetworkManagerWlanApi::GetAccessPointProperty(DBusGProxy* proxy, 320 dbus::Response* NetworkManagerWlanApi::GetAccessPointProperty(
381 const char* property_name, 321 dbus::ObjectProxy* access_point_proxy,
382 int expected_gvalue_type, 322 const std::string& property_name) {
383 GValue* value_out) { 323 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, "Get");
384 dbus_g_proxy_call(proxy, "Get", &error_, 324 dbus::MessageWriter builder(&method_call);
385 G_TYPE_STRING, "org.freedesktop.NetworkManager.AccessPoint", 325 builder.AppendString("org.freedesktop.NetworkManager.AccessPoint");
386 G_TYPE_STRING, property_name, 326 builder.AppendString(property_name);
387 G_TYPE_INVALID, 327 dbus::Response* response = access_point_proxy->CallMethodAndBlock(
388 G_TYPE_VALUE, value_out, 328 &method_call,
389 G_TYPE_INVALID); 329 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
390 if (CheckError()) 330 if (!response) {
391 return false; 331 LOG(WARNING) << "Failed to get property for " << property_name;
392 if (!G_VALUE_HOLDS(value_out, expected_gvalue_type)) {
393 DLOG(WARNING) << "Property " << property_name << " unexptected type "
394 << G_VALUE_TYPE(value_out);
395 return false;
396 } 332 }
397 return true; 333 return response;
398 } 334 }
399 335
400 } // namespace 336 } // namespace
401 337
402 // static 338 // static
403 template<> 339 template<>
404 WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() { 340 WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
405 return new WifiDataProviderLinux(); 341 return new WifiDataProviderLinux();
406 } 342 }
407 343
(...skipping 10 matching lines...) Expand all
418 return wlan_api.release(); 354 return wlan_api.release();
419 return NULL; 355 return NULL;
420 } 356 }
421 357
422 PollingPolicyInterface* WifiDataProviderLinux::NewPollingPolicy() { 358 PollingPolicyInterface* WifiDataProviderLinux::NewPollingPolicy() {
423 return new GenericPollingPolicy<kDefaultPollingIntervalMilliseconds, 359 return new GenericPollingPolicy<kDefaultPollingIntervalMilliseconds,
424 kNoChangePollingIntervalMilliseconds, 360 kNoChangePollingIntervalMilliseconds,
425 kTwoNoChangePollingIntervalMilliseconds, 361 kTwoNoChangePollingIntervalMilliseconds,
426 kNoWifiPollingIntervalMilliseconds>; 362 kNoWifiPollingIntervalMilliseconds>;
427 } 363 }
364
365 WifiDataProviderCommon::WlanApiInterface*
366 WifiDataProviderLinux::NewWlanApiForTesting(dbus::Bus* bus) {
367 scoped_ptr<NetworkManagerWlanApi> wlan_api(new NetworkManagerWlanApi);
368 if (wlan_api->InitWithBus(bus))
369 return wlan_api.release();
370 return NULL;
371 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698