summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsatorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-25 21:26:17 +0000
committersatorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-25 21:26:17 +0000
commit34168967957a98806999ed30da341823e973dda4 (patch)
tree8beadb9e42239690818122db652e8253412ab4a4
parent0e935c74fd6ca38866df63af66dc535497172950 (diff)
downloadchromium_src-34168967957a98806999ed30da341823e973dda4.zip
chromium_src-34168967957a98806999ed30da341823e973dda4.tar.gz
chromium_src-34168967957a98806999ed30da341823e973dda4.tar.bz2
Rework wifi_data_provider_linux.cc with our D-Bus library.
The code is now a lot simpler, and unit tested. The dlopen hack and the timeout hack are now gone. BUG=90036 TEST=confirm that the geolocation works on maps.google.com on a device with wifi network Review URL: http://codereview.chromium.org/7725001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98307 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/chrome_tests.gypi4
-rw-r--r--content/DEPS1
-rw-r--r--content/browser/geolocation/wifi_data_provider_linux.cc453
-rw-r--r--content/browser/geolocation/wifi_data_provider_linux.h9
-rw-r--r--content/browser/geolocation/wifi_data_provider_linux_unittest.cc221
-rw-r--r--content/content_browser.gypi3
6 files changed, 437 insertions, 254 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 74e60db..d7ca942 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -2009,6 +2009,7 @@
'../content/browser/geolocation/location_arbitrator_unittest.cc',
'../content/browser/geolocation/network_location_provider_unittest.cc',
'../content/browser/geolocation/wifi_data_provider_common_unittest.cc',
+ '../content/browser/geolocation/wifi_data_provider_linux_unittest.cc',
'../content/browser/geolocation/wifi_data_provider_unittest_win.cc',
'../content/browser/geolocation/win7_location_api_unittest_win.cc',
'../content/browser/geolocation/win7_location_provider_unittest_win.cc',
@@ -2086,6 +2087,7 @@
['chromeos==1', {
'sources/': [
['exclude', '^browser/password_manager/native_backend_gnome_x_unittest.cc'],
+ ['exclude', '^../content/browser/geolocation/wifi_data_provider_linux_unittest.cc'],
# TODO(thestig) Enable PrintPreviewUI tests on CrOS when
# print preview is enabled on CrOS.
['exclude', '^browser/ui/webui/print_preview_ui_unittest.cc'],
@@ -2136,8 +2138,10 @@
}],
],
'dependencies': [
+ '../build/linux/system.gyp:dbus',
'../build/linux/system.gyp:gtk',
'../build/linux/system.gyp:ssl',
+ '../dbus/dbus.gyp:dbus_test_support',
'../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
],
'sources!': [
diff --git a/content/DEPS b/content/DEPS
index 24476e0..b05fedd 100644
--- a/content/DEPS
+++ b/content/DEPS
@@ -21,6 +21,7 @@ include_rules = [
"+content/common",
"+content/test",
+ "+dbus",
"+grit",
"+gpu",
"+net",
diff --git a/content/browser/geolocation/wifi_data_provider_linux.cc b/content/browser/geolocation/wifi_data_provider_linux.cc
index c1a6a04..178260a 100644
--- a/content/browser/geolocation/wifi_data_provider_linux.cc
+++ b/content/browser/geolocation/wifi_data_provider_linux.cc
@@ -8,15 +8,12 @@
#include "content/browser/geolocation/wifi_data_provider_linux.h"
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <dbus/dbus.h>
-#include <dlfcn.h>
-#include <glib.h>
-
#include "base/memory/scoped_ptr.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "dbus/object_proxy.h"
namespace {
// The time periods between successive polls of the wifi data.
@@ -32,67 +29,6 @@ const char kNetworkManagerInterface[] = "org.freedesktop.NetworkManager";
// From http://projects.gnome.org/NetworkManager/developers/spec.html
enum { NM_DEVICE_TYPE_WIFI = 2 };
-// Function type matching dbus_g_bus_get_private so that we can
-// dynamically determine the presence of this symbol (see
-// NetworkManagerWlanApi::Init)
-typedef DBusGConnection* DBusGBusGetPrivateFunc(
- DBusBusType type, GMainContext* context, GError** error);
-
-// Utility wrappers to make various GLib & DBus structs into scoped objects.
-class ScopedGPtrArrayFree {
- public:
- void operator()(GPtrArray* x) const {
- if (x)
- g_ptr_array_free(x, TRUE);
- }
-};
-// Use ScopedGPtrArrayPtr as if it were scoped_ptr<GPtrArray>
-typedef scoped_ptr_malloc<GPtrArray, ScopedGPtrArrayFree> ScopedGPtrArrayPtr;
-
-class ScopedGObjectFree {
- public:
- void operator()(void* x) const {
- if (x)
- g_object_unref(x);
- }
-};
-// Use ScopedDBusGProxyPtr as if it were scoped_ptr<DBusGProxy>
-typedef scoped_ptr_malloc<DBusGProxy, ScopedGObjectFree> ScopedDBusGProxyPtr;
-
-// Use ScopedGValue::v as an instance of GValue with automatic cleanup.
-class ScopedGValue {
- public:
- ScopedGValue()
- : v(empty_gvalue()) {
- }
- ~ScopedGValue() {
- g_value_unset(&v);
- }
- static GValue empty_gvalue() {
- GValue value = {0};
- return value;
- }
-
- GValue v;
-};
-
-// Use ScopedDLHandle to automatically clean up after dlopen.
-class ScopedDLHandle {
- public:
- ScopedDLHandle(void* handle)
- : handle_(handle) {
- }
- ~ScopedDLHandle() {
- if (handle_)
- dlclose(handle_);
- }
- void* get() {
- return handle_;
- }
- private:
- void *handle_;
-};
-
// Wifi API binding to NetworkManager, to allow reuse of the polling behavior
// defined in WifiDataProviderCommon.
// TODO(joth): NetworkManager also allows for notification based handling,
@@ -108,41 +44,34 @@ class NetworkManagerWlanApi : public WifiDataProviderCommon::WlanApiInterface {
// in which case no other method may be called.
bool Init();
+ // Similar to Init() but can inject the bus object. Used for testing.
+ bool InitWithBus(dbus::Bus* bus);
+
// WifiDataProviderCommon::WlanApiInterface
- bool GetAccessPointData(WifiData::AccessPointDataSet* data);
+ //
+ // This function makes blocking D-Bus calls, but it's totally fine as
+ // the code runs in "Geolocation" thread, not the browser's UI thread.
+ virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data);
private:
- // Checks if the last dbus call returned an error. If it did, logs the error
- // message, frees it and returns true.
- // This must be called after every dbus call that accepts |&error_|
- bool CheckError();
-
// Enumerates the list of available network adapter devices known to
- // NetworkManager. Ownership of the array (and contained objects) is returned
- // to the caller.
- GPtrArray* GetAdapterDeviceList();
+ // NetworkManager. Return true on success.
+ bool GetAdapterDeviceList(std::vector<std::string>* device_paths);
// Given the NetworkManager path to a wireless adapater, dumps the wifi scan
// results and appends them to |data|. Returns false if a fatal error is
// encountered such that the data set could not be populated.
- bool GetAccessPointsForAdapter(const gchar* adapter_path,
+ bool GetAccessPointsForAdapter(const std::string& adapter_path,
WifiData::AccessPointDataSet* data);
// Internal method used by |GetAccessPointsForAdapter|, given a wifi access
- // point proxy retrieves the named property into |value_out|. Returns false if
- // the property could not be read, or is not of type |expected_gvalue_type|.
- bool GetAccessPointProperty(DBusGProxy* proxy, const char* property_name,
- int expected_gvalue_type, GValue* value_out);
-
- // Error from the last dbus call. NULL when there's no error. Freed and
- // cleared by CheckError().
- GError* error_;
- // Connection to the dbus system bus.
- DBusGConnection* connection_;
- // Main context
- GMainContext* context_;
- // Proxy to the network manager dbus service.
- ScopedDBusGProxyPtr proxy_;
+ // point proxy retrieves the named property and returns it. Returns NULL if
+ // the property could not be read.
+ dbus::Response* GetAccessPointProperty(dbus::ObjectProxy* proxy,
+ const std::string& property_name);
+
+ scoped_refptr<dbus::Bus> system_bus_;
+ dbus::ObjectProxy* network_manager_proxy_;
DISALLOW_COPY_AND_ASSIGN(NetworkManagerWlanApi);
};
@@ -161,102 +90,73 @@ int frquency_in_khz_to_channel(int frequency_khz) {
}
NetworkManagerWlanApi::NetworkManagerWlanApi()
- : error_(NULL),
- connection_(NULL),
- context_(NULL)
-{
+ : network_manager_proxy_(NULL) {
}
NetworkManagerWlanApi::~NetworkManagerWlanApi() {
- proxy_.reset();
- if (connection_) {
- dbus_connection_close(dbus_g_connection_get_connection(connection_));
- dbus_g_connection_unref(connection_);
- }
- if (context_)
- g_main_context_unref(context_);
-
- DCHECK(!error_) << "Missing a call to CheckError() to clear |error_|";
+ // Close the connection.
+ system_bus_->ShutdownAndBlock();
}
bool NetworkManagerWlanApi::Init() {
- // Chrome DLL init code handles initializing the thread system, so rather than
- // get caught up with that nonsense here, lets just assert our requirement.
- CHECK(g_thread_supported());
-
- // We require a private bus to ensure that we don't interfere with the
- // default loop on the main thread. Unforunately this functionality is only
- // available in dbus-glib-0.84 and later. We do a dynamic symbol lookup
- // to determine if dbus_g_bus_get_private is available. See bug
- // http://code.google.com/p/chromium/issues/detail?id=59913 for more
- // information.
- ScopedDLHandle handle(dlopen(NULL, RTLD_LAZY));
- if (!handle.get())
- return false;
-
- DBusGBusGetPrivateFunc *my_dbus_g_bus_get_private =
- (DBusGBusGetPrivateFunc *) dlsym(handle.get(), "dbus_g_bus_get_private");
-
- if (!my_dbus_g_bus_get_private) {
- LOG(ERROR) << "We need dbus-glib >= 0.84 for wifi geolocation.";
- return false;
- }
- // Get a private connection to the session bus.
- context_ = g_main_context_new();
- DCHECK(context_);
- connection_ = my_dbus_g_bus_get_private(DBUS_BUS_SYSTEM, context_, &error_);
-
- if (CheckError())
- return false;
- DCHECK(connection_);
-
- // Disable timers on the connection since we don't need them and
- // we're not going to run them anyway as the connection is associated
- // with a private context. See bug http://crbug.com/40803
- dbus_bool_t ok = dbus_connection_set_timeout_functions(
- dbus_g_connection_get_connection(connection_),
- NULL, NULL, NULL, NULL, NULL);
- DCHECK(ok);
-
- proxy_.reset(dbus_g_proxy_new_for_name(connection_,
- kNetworkManagerServiceName,
- kNetworkManagerPath,
- kNetworkManagerInterface));
- DCHECK(proxy_.get());
+ dbus::Bus::Options options;
+ options.bus_type = dbus::Bus::SYSTEM;
+ options.connection_type = dbus::Bus::PRIVATE;
+ return InitWithBus(new dbus::Bus(options));
+}
+bool NetworkManagerWlanApi::InitWithBus(dbus::Bus* bus) {
+ system_bus_ = bus;
+ // system_bus_ will own all object proxies created from the bus.
+ network_manager_proxy_ =
+ system_bus_->GetObjectProxy(kNetworkManagerServiceName,
+ kNetworkManagerPath);
// Validate the proxy object by checking we can enumerate devices.
- ScopedGPtrArrayPtr device_list(GetAdapterDeviceList());
- return !!device_list.get();
+ std::vector<std::string> adapter_paths;
+ const bool success = GetAdapterDeviceList(&adapter_paths);
+ VLOG(1) << "Init() result: " << success;
+ return success;
}
bool NetworkManagerWlanApi::GetAccessPointData(
WifiData::AccessPointDataSet* data) {
- ScopedGPtrArrayPtr device_list(GetAdapterDeviceList());
- if (device_list == NULL) {
- DLOG(WARNING) << "Could not enumerate access points";
+ std::vector<std::string> device_paths;
+ if (!GetAdapterDeviceList(&device_paths)) {
+ LOG(WARNING) << "Could not enumerate access points";
return false;
}
int success_count = 0;
int fail_count = 0;
// Iterate the devices, getting APs for each wireless adapter found
- for (guint i = 0; i < device_list->len; i++) {
- const gchar* device_path =
- reinterpret_cast<const gchar*>(g_ptr_array_index(device_list, i));
-
- ScopedDBusGProxyPtr device_properties_proxy(dbus_g_proxy_new_from_proxy(
- proxy_.get(), DBUS_INTERFACE_PROPERTIES, device_path));
- ScopedGValue device_type_g_value;
- dbus_g_proxy_call(device_properties_proxy.get(), "Get", &error_,
- G_TYPE_STRING, "org.freedesktop.NetworkManager.Device",
- G_TYPE_STRING, "DeviceType",
- G_TYPE_INVALID,
- G_TYPE_VALUE, &device_type_g_value.v,
- G_TYPE_INVALID);
- if (CheckError())
- continue;
-
- const guint device_type = g_value_get_uint(&device_type_g_value.v);
+ for (size_t i = 0; i < device_paths.size(); ++i) {
+ const std::string& device_path = device_paths[i];
+ VLOG(1) << "Checking device: " << device_path;
+
+ dbus::ObjectProxy* device_proxy =
+ system_bus_->GetObjectProxy(kNetworkManagerServiceName,
+ device_path);
+
+ dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, "Get");
+ dbus::MessageWriter builder(&method_call);
+ builder.AppendString("org.freedesktop.NetworkManager.Device");
+ builder.AppendString("DeviceType");
+ scoped_ptr<dbus::Response> response(
+ device_proxy->CallMethodAndBlock(
+ &method_call,
+ dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
+ if (!response.get()) {
+ LOG(WARNING) << "Failed to get the device type for " << device_path;
+ continue; // Check the next device.
+ }
+ dbus::MessageReader reader(response.get());
+ uint32 device_type = 0;
+ if (!reader.PopVariantOfUint32(&device_type)) {
+ LOG(WARNING) << "Unexpected response for " << device_type << ": "
+ << response->ToString();
+ continue; // Check the next device.
+ }
+ VLOG(1) << "Device type: " << device_type;
if (device_type == NM_DEVICE_TYPE_WIFI) { // Found a wlan adapter
if (GetAccessPointsForAdapter(device_path, data))
@@ -269,84 +169,107 @@ bool NetworkManagerWlanApi::GetAccessPointData(
return success_count || fail_count == 0;
}
-bool NetworkManagerWlanApi::CheckError() {
- if (error_) {
- LOG(ERROR) << "Failed to complete NetworkManager call: " << error_->message;
- g_error_free(error_);
- error_ = NULL;
- return true;
+bool NetworkManagerWlanApi::GetAdapterDeviceList(
+ std::vector<std::string>* device_paths) {
+ dbus::MethodCall method_call(kNetworkManagerInterface, "GetDevices");
+ scoped_ptr<dbus::Response> response(
+ network_manager_proxy_->CallMethodAndBlock(
+ &method_call,
+ dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
+ if (!response.get()) {
+ LOG(WARNING) << "Failed to get the device list";
+ return false;
}
- return false;
-}
-GPtrArray* NetworkManagerWlanApi::GetAdapterDeviceList() {
- GPtrArray* device_list = NULL;
- dbus_g_proxy_call(proxy_.get(), "GetDevices", &error_,
- G_TYPE_INVALID,
- dbus_g_type_get_collection("GPtrArray",
- DBUS_TYPE_G_OBJECT_PATH),
- &device_list,
- G_TYPE_INVALID);
- if (CheckError())
- return NULL;
- return device_list;
+ dbus::MessageReader reader(response.get());
+ if (!reader.PopArrayOfObjectPaths(device_paths)) {
+ LOG(WARNING) << "Unexpected response: " << response->ToString();
+ return false;
+ }
+ return true;
}
-bool NetworkManagerWlanApi::GetAccessPointsForAdapter(
- const gchar* adapter_path, WifiData::AccessPointDataSet* data) {
- DCHECK(proxy_.get());
+bool NetworkManagerWlanApi::GetAccessPointsForAdapter(
+ const std::string& adapter_path, WifiData::AccessPointDataSet* data) {
// Create a proxy object for this wifi adapter, and ask it to do a scan
// (or at least, dump its scan results).
- ScopedDBusGProxyPtr wifi_adapter_proxy(dbus_g_proxy_new_from_proxy(
- proxy_.get(), "org.freedesktop.NetworkManager.Device.Wireless",
- adapter_path));
-
- GPtrArray* ap_list_raw = NULL;
- // Enumerate the access points for this adapter.
- dbus_g_proxy_call(wifi_adapter_proxy.get(), "GetAccessPoints", &error_,
- G_TYPE_INVALID,
- dbus_g_type_get_collection("GPtrArray",
- DBUS_TYPE_G_OBJECT_PATH),
- &ap_list_raw,
- G_TYPE_INVALID);
- ScopedGPtrArrayPtr ap_list(ap_list_raw); // Takes ownership.
- ap_list_raw = NULL;
-
- if (CheckError())
+ dbus::ObjectProxy* device_proxy =
+ system_bus_->GetObjectProxy(kNetworkManagerServiceName,
+ adapter_path);
+ dbus::MethodCall method_call(
+ "org.freedesktop.NetworkManager.Device.Wireless",
+ "GetAccessPoints");
+ scoped_ptr<dbus::Response> response(
+ device_proxy->CallMethodAndBlock(
+ &method_call,
+ dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
+ if (!response.get()) {
+ LOG(WARNING) << "Failed to get access points data for " << adapter_path;
+ return false;
+ }
+ dbus::MessageReader reader(response.get());
+ std::vector<std::string> access_point_paths;
+ if (!reader.PopArrayOfObjectPaths(&access_point_paths)) {
+ LOG(WARNING) << "Unexpected response for " << adapter_path << ": "
+ << response->ToString();
return false;
+ }
+
+ VLOG(1) << "Wireless adapter " << adapter_path << " found "
+ << access_point_paths.size() << " access points.";
- DVLOG(1) << "Wireless adapter " << adapter_path << " found " << ap_list->len
- << " access points.";
+ for (size_t i = 0; i < access_point_paths.size(); ++i) {
+ const std::string& access_point_path = access_point_paths[i];
+ VLOG(1) << "Checking access point: " << access_point_path;
- for (guint i = 0; i < ap_list->len; i++) {
- const gchar* ap_path =
- reinterpret_cast<const gchar*>(g_ptr_array_index(ap_list, i));
- ScopedDBusGProxyPtr access_point_proxy(dbus_g_proxy_new_from_proxy(
- proxy_.get(), DBUS_INTERFACE_PROPERTIES, ap_path));
+ dbus::ObjectProxy* access_point_proxy =
+ system_bus_->GetObjectProxy(kNetworkManagerServiceName,
+ access_point_path);
AccessPointData access_point_data;
- { // Read SSID.
- ScopedGValue ssid_g_value;
- if (!GetAccessPointProperty(access_point_proxy.get(), "Ssid",
- G_TYPE_BOXED, &ssid_g_value.v))
+ {
+ scoped_ptr<dbus::Response> response(
+ GetAccessPointProperty(access_point_proxy, "Ssid"));
+ if (!response.get())
continue;
- const GArray* ssid =
- reinterpret_cast<const GArray*>(g_value_get_boxed(&ssid_g_value.v));
- UTF8ToUTF16(ssid->data, ssid->len, &access_point_data.ssid);
+ // The response should contain a variant that contains an array of bytes.
+ dbus::MessageReader reader(response.get());
+ dbus::MessageReader variant_reader(response.get());
+ if (!reader.PopVariant(&variant_reader)) {
+ LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
+ << response->ToString();
+ continue;
+ }
+ uint8* ssid_bytes = NULL;
+ size_t ssid_length = 0;
+ if (!variant_reader.PopArrayOfBytes(&ssid_bytes, &ssid_length)) {
+ LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
+ << response->ToString();
+ continue;
+ }
+ std::string ssid(ssid_bytes, ssid_bytes + ssid_length);
+ access_point_data.ssid = UTF8ToUTF16(ssid);
}
{ // Read the mac address
- ScopedGValue mac_g_value;
- if (!GetAccessPointProperty(access_point_proxy.get(), "HwAddress",
- G_TYPE_STRING, &mac_g_value.v))
+ scoped_ptr<dbus::Response> response(
+ GetAccessPointProperty(access_point_proxy, "HwAddress"));
+ if (!response.get())
continue;
- std::string mac = g_value_get_string(&mac_g_value.v);
+ dbus::MessageReader reader(response.get());
+ std::string mac;
+ if (!reader.PopVariantOfString(&mac)) {
+ LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
+ << response->ToString();
+ continue;
+ }
+
ReplaceSubstringsAfterOffset(&mac, 0U, ":", "");
std::vector<uint8> mac_bytes;
if (!base::HexStringToBytes(mac, &mac_bytes) || mac_bytes.size() != 6) {
- DLOG(WARNING) << "Can't parse mac address (found " << mac_bytes.size()
- << " bytes) so using raw string: " << mac;
+ LOG(WARNING) << "Can't parse mac address (found " << mac_bytes.size()
+ << " bytes) so using raw string: " << mac;
access_point_data.mac_address = UTF8ToUTF16(mac);
} else {
access_point_data.mac_address = MacAddressAsString16(&mac_bytes[0]);
@@ -354,47 +277,63 @@ bool NetworkManagerWlanApi::GetAccessPointsForAdapter(
}
{ // Read signal strength.
- ScopedGValue signal_g_value;
- if (!GetAccessPointProperty(access_point_proxy.get(), "Strength",
- G_TYPE_UCHAR, &signal_g_value.v))
+ scoped_ptr<dbus::Response> response(
+ GetAccessPointProperty(access_point_proxy, "Strength"));
+ if (!response.get())
continue;
+ dbus::MessageReader reader(response.get());
+ uint8 strength = 0;
+ if (!reader.PopVariantOfByte(&strength)) {
+ LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
+ << response->ToString();
+ continue;
+ }
// Convert strength as a percentage into dBs.
- access_point_data.radio_signal_strength =
- -100 + g_value_get_uchar(&signal_g_value.v) / 2;
+ access_point_data.radio_signal_strength = -100 + strength / 2;
}
{ // Read the channel
- ScopedGValue freq_g_value;
- if (!GetAccessPointProperty(access_point_proxy.get(), "Frequency",
- G_TYPE_UINT, &freq_g_value.v))
+ scoped_ptr<dbus::Response> response(
+ GetAccessPointProperty(access_point_proxy, "Frequency"));
+ if (!response.get())
continue;
+ dbus::MessageReader reader(response.get());
+ uint32 frequency = 0;
+ if (!reader.PopVariantOfUint32(&frequency)) {
+ LOG(WARNING) << "Unexpected response for " << access_point_path << ": "
+ << response->ToString();
+ continue;
+ }
+
// NetworkManager returns frequency in MHz.
access_point_data.channel =
- frquency_in_khz_to_channel(g_value_get_uint(&freq_g_value.v) * 1000);
+ frquency_in_khz_to_channel(frequency * 1000);
}
+ VLOG(1) << "Access point data of " << access_point_path << ": "
+ << "SSID: " << access_point_data.ssid << ", "
+ << "MAC: " << access_point_data.mac_address << ", "
+ << "Strength: " << access_point_data.radio_signal_strength << ", "
+ << "Channel: " << access_point_data.channel;
+
data->insert(access_point_data);
}
return true;
}
-bool NetworkManagerWlanApi::GetAccessPointProperty(DBusGProxy* proxy,
- const char* property_name,
- int expected_gvalue_type,
- GValue* value_out) {
- dbus_g_proxy_call(proxy, "Get", &error_,
- G_TYPE_STRING, "org.freedesktop.NetworkManager.AccessPoint",
- G_TYPE_STRING, property_name,
- G_TYPE_INVALID,
- G_TYPE_VALUE, value_out,
- G_TYPE_INVALID);
- if (CheckError())
- return false;
- if (!G_VALUE_HOLDS(value_out, expected_gvalue_type)) {
- DLOG(WARNING) << "Property " << property_name << " unexptected type "
- << G_VALUE_TYPE(value_out);
- return false;
+dbus::Response* NetworkManagerWlanApi::GetAccessPointProperty(
+ dbus::ObjectProxy* access_point_proxy,
+ const std::string& property_name) {
+ dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, "Get");
+ dbus::MessageWriter builder(&method_call);
+ builder.AppendString("org.freedesktop.NetworkManager.AccessPoint");
+ builder.AppendString(property_name);
+ dbus::Response* response = access_point_proxy->CallMethodAndBlock(
+ &method_call,
+ dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
+ if (!response) {
+ LOG(WARNING) << "Failed to get property for " << property_name;
}
- return true;
+ return response;
}
} // namespace
@@ -425,3 +364,11 @@ PollingPolicyInterface* WifiDataProviderLinux::NewPollingPolicy() {
kTwoNoChangePollingIntervalMilliseconds,
kNoWifiPollingIntervalMilliseconds>;
}
+
+WifiDataProviderCommon::WlanApiInterface*
+WifiDataProviderLinux::NewWlanApiForTesting(dbus::Bus* bus) {
+ scoped_ptr<NetworkManagerWlanApi> wlan_api(new NetworkManagerWlanApi);
+ if (wlan_api->InitWithBus(bus))
+ return wlan_api.release();
+ return NULL;
+}
diff --git a/content/browser/geolocation/wifi_data_provider_linux.h b/content/browser/geolocation/wifi_data_provider_linux.h
index 978bd8f..434e6e5 100644
--- a/content/browser/geolocation/wifi_data_provider_linux.h
+++ b/content/browser/geolocation/wifi_data_provider_linux.h
@@ -8,17 +8,26 @@
#include "content/browser/geolocation/wifi_data_provider_common.h"
+namespace dbus {
+class Bus;
+};
+
class WifiDataProviderLinux : public WifiDataProviderCommon {
public:
WifiDataProviderLinux();
private:
+ friend class GeolocationWifiDataProviderLinuxTest;
+
virtual ~WifiDataProviderLinux();
// WifiDataProviderCommon
virtual WlanApiInterface* NewWlanApi();
virtual PollingPolicyInterface* NewPollingPolicy();
+ // For testing.
+ WlanApiInterface* NewWlanApiForTesting(dbus::Bus* bus);
+
DISALLOW_COPY_AND_ASSIGN(WifiDataProviderLinux);
};
diff --git a/content/browser/geolocation/wifi_data_provider_linux_unittest.cc b/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
new file mode 100644
index 0000000..e5a39b9
--- /dev/null
+++ b/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
@@ -0,0 +1,221 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/geolocation/wifi_data_provider_linux.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "dbus/message.h"
+#include "dbus/mock_bus.h"
+#include "dbus/mock_object_proxy.h"
+#include "dbus/object_proxy.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::Unused;
+
+class GeolocationWifiDataProviderLinuxTest : public testing::Test {
+ void SetUp() {
+ // Create a mock bus.
+ dbus::Bus::Options options;
+ options.bus_type = dbus::Bus::SYSTEM;
+ mock_bus_ = new dbus::MockBus(options);
+
+ // Create a mock proxy that behaves as NetworkManager.
+ mock_network_manager_proxy_ =
+ new dbus::MockObjectProxy(mock_bus_.get(),
+ "org.freedesktop.NetworkManager",
+ "/org/freedesktop/NetworkManager");
+ // Set an expectation so mock_network_manager_proxy_'s
+ // CallMethodAndBlock() will use CreateNetowrkManagerProxyResponse()
+ // to return responses.
+ EXPECT_CALL(*mock_network_manager_proxy_,
+ CallMethodAndBlock(_, _))
+ .WillRepeatedly(Invoke(
+ this,
+ &GeolocationWifiDataProviderLinuxTest::
+ CreateNetowrkManagerProxyResponse));
+
+ // Create a mock proxy that behaves as NetworkManager/Devices/0.
+ mock_device_proxy_ =
+ new dbus::MockObjectProxy(mock_bus_.get(),
+ "org.freedesktop.NetworkManager",
+ "/org/freedesktop/NetworkManager/Devices/0");
+ EXPECT_CALL(*mock_device_proxy_,
+ CallMethodAndBlock(_, _))
+ .WillRepeatedly(Invoke(
+ this,
+ &GeolocationWifiDataProviderLinuxTest::CreateDeviceProxyResponse));
+
+ // Create a mock proxy that behaves as NetworkManager/AccessPoint/0.
+ mock_access_point_proxy_ =
+ new dbus::MockObjectProxy(
+ mock_bus_.get(),
+ "org.freedesktop.NetworkManager",
+ "/org/freedesktop/NetworkManager/AccessPoint/0");
+ EXPECT_CALL(*mock_access_point_proxy_,
+ CallMethodAndBlock(_, _))
+ .WillRepeatedly(Invoke(
+ this,
+ &GeolocationWifiDataProviderLinuxTest::
+ CreateAccessPointProxyResponse));
+
+ // Set an expectation so mock_bus_'s GetObjectProxy() for the given
+ // service name and the object path will return
+ // mock_network_manager_proxy_.
+ EXPECT_CALL(*mock_bus_, GetObjectProxy(
+ "org.freedesktop.NetworkManager",
+ "/org/freedesktop/NetworkManager"))
+ .WillOnce(Return(mock_network_manager_proxy_.get()));
+ // Likewise, set an expectation for mock_device_proxy_.
+ EXPECT_CALL(*mock_bus_, GetObjectProxy(
+ "org.freedesktop.NetworkManager",
+ "/org/freedesktop/NetworkManager/Devices/0"))
+ .WillOnce(Return(mock_device_proxy_.get()))
+ .WillOnce(Return(mock_device_proxy_.get()));
+ // Likewise, set an expectation for mock_access_point_proxy_.
+ EXPECT_CALL(*mock_bus_, GetObjectProxy(
+ "org.freedesktop.NetworkManager",
+ "/org/freedesktop/NetworkManager/AccessPoint/0"))
+ .WillOnce(Return(mock_access_point_proxy_.get()));
+
+ // ShutdownAndBlock() should be called.
+ EXPECT_CALL(*mock_bus_, ShutdownAndBlock()).WillOnce(Return());
+
+ // Create the wlan API with the mock bus object injected.
+ wifi_provider_linux_ = new WifiDataProviderLinux;
+ wlan_api_.reset(
+ wifi_provider_linux_->NewWlanApiForTesting(mock_bus_.get()));
+ ASSERT_TRUE(wlan_api_.get());
+ }
+
+ protected:
+ // DeviceDataProviderImplBase, a super class of WifiDataProviderLinux,
+ // requires a message loop to be present. message_loop_ is defined here,
+ // as it should outlive wifi_provider_linux_.
+ MessageLoop message_loop_;
+ scoped_refptr<dbus::MockBus> mock_bus_;
+ scoped_refptr<dbus::MockObjectProxy> mock_network_manager_proxy_;
+ scoped_refptr<dbus::MockObjectProxy> mock_access_point_proxy_;
+ scoped_refptr<dbus::MockObjectProxy> mock_device_proxy_;
+ scoped_refptr<WifiDataProviderLinux> wifi_provider_linux_;
+ scoped_ptr<WifiDataProviderCommon::WlanApiInterface> wlan_api_;
+
+ private:
+ // Creates a response for |mock_network_manager_proxy_|.
+ dbus::Response* CreateNetowrkManagerProxyResponse(
+ dbus::MethodCall* method_call,
+ Unused) {
+ if (method_call->GetInterface() == "org.freedesktop.NetworkManager" &&
+ method_call->GetMember() == "GetDevices") {
+ // The list of devices is asked. Return the object path.
+ std::vector<std::string> object_paths;
+ object_paths.push_back("/org/freedesktop/NetworkManager/Devices/0");
+
+ dbus::Response* response = dbus::Response::CreateEmpty();
+ dbus::MessageWriter writer(response);
+ writer.AppendArrayOfObjectPaths(object_paths);
+ return response;
+ }
+
+ LOG(ERROR) << "Unexpected method call: " << method_call->ToString();
+ return NULL;
+ }
+
+ // Creates a response for |mock_device_proxy_|.
+ dbus::Response* CreateDeviceProxyResponse(dbus::MethodCall* method_call,
+ Unused) {
+ if (method_call->GetInterface() == DBUS_INTERFACE_PROPERTIES &&
+ method_call->GetMember() == "Get") {
+ dbus::MessageReader reader(method_call);
+ std::string interface_name;
+ std::string property_name;
+ if (reader.PopString(&interface_name) &&
+ reader.PopString(&property_name)) {
+ // The device type is asked. Respond that the device type is wifi.
+ dbus::Response* response = dbus::Response::CreateEmpty();
+ dbus::MessageWriter writer(response);
+ // This matches NM_DEVICE_TYPE_WIFI in wifi_data_provider_linux.cc.
+ const int kDeviceTypeWifi = 2;
+ writer.AppendVariantOfUint32(kDeviceTypeWifi);
+ return response;
+ }
+ } else if (method_call->GetInterface() ==
+ "org.freedesktop.NetworkManager.Device.Wireless" &&
+ method_call->GetMember() == "GetAccessPoints") {
+ // The list of access points is asked. Return the object path.
+ dbus::Response* response = dbus::Response::CreateEmpty();
+ dbus::MessageWriter writer(response);
+ std::vector<std::string> object_paths;
+ object_paths.push_back("/org/freedesktop/NetworkManager/AccessPoint/0");
+ writer.AppendArrayOfObjectPaths(object_paths);
+ return response;
+ }
+
+ LOG(ERROR) << "Unexpected method call: " << method_call->ToString();
+ return NULL;
+ }
+
+
+ // Creates a response for |mock_access_point_proxy_|.
+ dbus::Response* CreateAccessPointProxyResponse(dbus::MethodCall* method_call,
+ Unused) {
+ if (method_call->GetInterface() == DBUS_INTERFACE_PROPERTIES &&
+ method_call->GetMember() == "Get") {
+ dbus::MessageReader reader(method_call);
+
+ std::string interface_name;
+ std::string property_name;
+ if (reader.PopString(&interface_name) &&
+ reader.PopString(&property_name)) {
+ dbus::Response* response = dbus::Response::CreateEmpty();
+ dbus::MessageWriter writer(response);
+
+ if (property_name == "Ssid") {
+ const uint8 kSsid[] = {0x74, 0x65, 0x73, 0x74}; // "test"
+ dbus::MessageWriter variant_writer(response);
+ writer.OpenVariant("ay", &variant_writer);
+ variant_writer.AppendArrayOfBytes(kSsid, arraysize(kSsid));
+ writer.CloseContainer(&variant_writer);
+ } else if (property_name == "HwAddress") {
+ // This will be converted to "00-11-22-33-44-55".
+ const std::string kMacAddress = "00:11:22:33:44:55";
+ writer.AppendVariantOfString(kMacAddress);
+ } else if (property_name == "Strength") {
+ // This will be converted to -50.
+ const uint8 kStrength = 100;
+ writer.AppendVariantOfByte(kStrength);
+ } else if (property_name == "Frequency") {
+ // This will be converted to channel 4.
+ const uint32 kFrequency = 2427;
+ writer.AppendVariantOfUint32(kFrequency);
+ }
+ return response;
+ }
+ }
+
+ LOG(ERROR) << "Unexpected method call: " << method_call->ToString();
+ return NULL;
+ }
+};
+
+TEST_F(GeolocationWifiDataProviderLinuxTest, GetAccessPointData) {
+ WifiData::AccessPointDataSet access_point_data_set;
+ ASSERT_TRUE(wlan_api_->GetAccessPointData(&access_point_data_set));
+
+ ASSERT_EQ(1U, access_point_data_set.size());
+ AccessPointData access_point_data = *access_point_data_set.begin();
+
+ // Check the contents of the access point data.
+ // The expected values come from CreateAccessPointProxyResponse() above.
+ EXPECT_EQ("test", UTF16ToUTF8(access_point_data.ssid));
+ EXPECT_EQ("00-11-22-33-44-55", UTF16ToUTF8(access_point_data.mac_address));
+ EXPECT_EQ(-50, access_point_data.radio_signal_strength);
+ EXPECT_EQ(4, access_point_data.channel);
+}
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index db946e5..93880eb 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -560,12 +560,13 @@
}],
['toolkit_uses_gtk == 1', {
'dependencies': [
- '../build/linux/system.gyp:dbus-glib',
+ '../build/linux/system.gyp:dbus',
# For FcLangSetAdd call in render_sandbox_host_linux.cc
'../build/linux/system.gyp:fontconfig',
'../build/linux/system.gyp:gtk',
# For XShm* in backing_store_x.cc
'../build/linux/system.gyp:x11',
+ '../dbus/dbus.gyp:dbus',
],
}],
['OS=="linux" and chromeos==1', {