This source file includes following definitions.
- frquency_in_khz_to_channel
- Init
- InitWithBus
- GetAccessPointData
- GetAdapterDeviceList
- GetAccessPointsForAdapter
- GetAccessPointProperty
- DefaultFactoryFunction
- NewWlanApi
- NewPollingPolicy
- NewWlanApiForTesting
#include "content/browser/geolocation/wifi_data_provider_linux.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
namespace content {
namespace {
const int kDefaultPollingIntervalMilliseconds = 10 * 1000;
const int kNoChangePollingIntervalMilliseconds = 2 * 60 * 1000;
const int kTwoNoChangePollingIntervalMilliseconds = 10 * 60 * 1000;
const int kNoWifiPollingIntervalMilliseconds = 20 * 1000;
const char kNetworkManagerServiceName[] = "org.freedesktop.NetworkManager";
const char kNetworkManagerPath[] = "/org/freedesktop/NetworkManager";
const char kNetworkManagerInterface[] = "org.freedesktop.NetworkManager";
enum { NM_DEVICE_TYPE_WIFI = 2 };
class NetworkManagerWlanApi : public WifiDataProviderCommon::WlanApiInterface {
public:
NetworkManagerWlanApi();
virtual ~NetworkManagerWlanApi();
bool Init();
bool InitWithBus(dbus::Bus* bus);
virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data) OVERRIDE;
private:
bool GetAdapterDeviceList(std::vector<dbus::ObjectPath>* device_paths);
bool GetAccessPointsForAdapter(const dbus::ObjectPath& adapter_path,
WifiData::AccessPointDataSet* data);
scoped_ptr<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);
};
int frquency_in_khz_to_channel(int frequency_khz) {
if (frequency_khz >= 2412000 && frequency_khz <= 2472000)
return (frequency_khz - 2407000) / 5000;
if (frequency_khz == 2484000)
return 14;
if (frequency_khz > 5000000 && frequency_khz < 6000000)
return (frequency_khz - 5000000) / 5000;
return AccessPointData().channel;
}
NetworkManagerWlanApi::NetworkManagerWlanApi()
: network_manager_proxy_(NULL) {
}
NetworkManagerWlanApi::~NetworkManagerWlanApi() {
system_bus_->ShutdownAndBlock();
}
bool NetworkManagerWlanApi::Init() {
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;
network_manager_proxy_ =
system_bus_->GetObjectProxy(kNetworkManagerServiceName,
dbus::ObjectPath(kNetworkManagerPath));
std::vector<dbus::ObjectPath> adapter_paths;
const bool success = GetAdapterDeviceList(&adapter_paths);
VLOG(1) << "Init() result: " << success;
return success;
}
bool NetworkManagerWlanApi::GetAccessPointData(
WifiData::AccessPointDataSet* data) {
std::vector<dbus::ObjectPath> device_paths;
if (!GetAdapterDeviceList(&device_paths)) {
LOG(WARNING) << "Could not enumerate access points";
return false;
}
int success_count = 0;
int fail_count = 0;
for (size_t i = 0; i < device_paths.size(); ++i) {
const dbus::ObjectPath& device_path = device_paths[i];
VLOG(1) << "Checking device: " << device_path.value();
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) {
LOG(WARNING) << "Failed to get the device type for "
<< device_path.value();
continue;
}
dbus::MessageReader reader(response.get());
uint32 device_type = 0;
if (!reader.PopVariantOfUint32(&device_type)) {
LOG(WARNING) << "Unexpected response for " << device_type << ": "
<< response->ToString();
continue;
}
VLOG(1) << "Device type: " << device_type;
if (device_type == NM_DEVICE_TYPE_WIFI) {
if (GetAccessPointsForAdapter(device_path, data))
++success_count;
else
++fail_count;
}
}
return success_count || fail_count == 0;
}
bool NetworkManagerWlanApi::GetAdapterDeviceList(
std::vector<dbus::ObjectPath>* 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) {
LOG(WARNING) << "Failed to get the device list";
return false;
}
dbus::MessageReader reader(response.get());
if (!reader.PopArrayOfObjectPaths(device_paths)) {
LOG(WARNING) << "Unexpected response: " << response->ToString();
return false;
}
return true;
}
bool NetworkManagerWlanApi::GetAccessPointsForAdapter(
const dbus::ObjectPath& adapter_path, WifiData::AccessPointDataSet* data) {
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) {
LOG(WARNING) << "Failed to get access points data for "
<< adapter_path.value();
return false;
}
dbus::MessageReader reader(response.get());
std::vector<dbus::ObjectPath> access_point_paths;
if (!reader.PopArrayOfObjectPaths(&access_point_paths)) {
LOG(WARNING) << "Unexpected response for " << adapter_path.value() << ": "
<< response->ToString();
return false;
}
VLOG(1) << "Wireless adapter " << adapter_path.value() << " found "
<< access_point_paths.size() << " access points.";
for (size_t i = 0; i < access_point_paths.size(); ++i) {
const dbus::ObjectPath& access_point_path = access_point_paths[i];
VLOG(1) << "Checking access point: " << access_point_path.value();
dbus::ObjectProxy* access_point_proxy =
system_bus_->GetObjectProxy(kNetworkManagerServiceName,
access_point_path);
AccessPointData access_point_data;
{
scoped_ptr<dbus::Response> response(
GetAccessPointProperty(access_point_proxy, "Ssid"));
if (!response)
continue;
dbus::MessageReader reader(response.get());
dbus::MessageReader variant_reader(response.get());
if (!reader.PopVariant(&variant_reader)) {
LOG(WARNING) << "Unexpected response for " << access_point_path.value()
<< ": " << response->ToString();
continue;
}
const 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.value()
<< ": " << response->ToString();
continue;
}
std::string ssid(ssid_bytes, ssid_bytes + ssid_length);
access_point_data.ssid = base::UTF8ToUTF16(ssid);
}
{
scoped_ptr<dbus::Response> response(
GetAccessPointProperty(access_point_proxy, "HwAddress"));
if (!response)
continue;
dbus::MessageReader reader(response.get());
std::string mac;
if (!reader.PopVariantOfString(&mac)) {
LOG(WARNING) << "Unexpected response for " << access_point_path.value()
<< ": " << response->ToString();
continue;
}
ReplaceSubstringsAfterOffset(&mac, 0U, ":", std::string());
std::vector<uint8> mac_bytes;
if (!base::HexStringToBytes(mac, &mac_bytes) || mac_bytes.size() != 6) {
LOG(WARNING) << "Can't parse mac address (found " << mac_bytes.size()
<< " bytes) so using raw string: " << mac;
access_point_data.mac_address = base::UTF8ToUTF16(mac);
} else {
access_point_data.mac_address = MacAddressAsString16(&mac_bytes[0]);
}
}
{
scoped_ptr<dbus::Response> response(
GetAccessPointProperty(access_point_proxy, "Strength"));
if (!response)
continue;
dbus::MessageReader reader(response.get());
uint8 strength = 0;
if (!reader.PopVariantOfByte(&strength)) {
LOG(WARNING) << "Unexpected response for " << access_point_path.value()
<< ": " << response->ToString();
continue;
}
access_point_data.radio_signal_strength = -100 + strength / 2;
}
{
scoped_ptr<dbus::Response> response(
GetAccessPointProperty(access_point_proxy, "Frequency"));
if (!response)
continue;
dbus::MessageReader reader(response.get());
uint32 frequency = 0;
if (!reader.PopVariantOfUint32(&frequency)) {
LOG(WARNING) << "Unexpected response for " << access_point_path.value()
<< ": " << response->ToString();
continue;
}
access_point_data.channel =
frquency_in_khz_to_channel(frequency * 1000);
}
VLOG(1) << "Access point data of " << access_point_path.value() << ": "
<< "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;
}
scoped_ptr<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);
scoped_ptr<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 response.Pass();
}
}
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new WifiDataProviderLinux();
}
WifiDataProviderLinux::WifiDataProviderLinux() {
}
WifiDataProviderLinux::~WifiDataProviderLinux() {
}
WifiDataProviderCommon::WlanApiInterface*
WifiDataProviderLinux::NewWlanApi() {
scoped_ptr<NetworkManagerWlanApi> wlan_api(new NetworkManagerWlanApi);
if (wlan_api->Init())
return wlan_api.release();
return NULL;
}
WifiPollingPolicy* WifiDataProviderLinux::NewPollingPolicy() {
return new GenericWifiPollingPolicy<kDefaultPollingIntervalMilliseconds,
kNoChangePollingIntervalMilliseconds,
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;
}
}