summaryrefslogtreecommitdiffstats
path: root/netwerk/wifi/dbus/DbusWifiScanner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/wifi/dbus/DbusWifiScanner.cpp')
-rw-r--r--netwerk/wifi/dbus/DbusWifiScanner.cpp161
1 files changed, 161 insertions, 0 deletions
diff --git a/netwerk/wifi/dbus/DbusWifiScanner.cpp b/netwerk/wifi/dbus/DbusWifiScanner.cpp
new file mode 100644
index 0000000000..43a6cc49dc
--- /dev/null
+++ b/netwerk/wifi/dbus/DbusWifiScanner.cpp
@@ -0,0 +1,161 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <gio/gio.h>
+#include "DbusWifiScanner.h"
+#include "nsWifiAccessPoint.h"
+#include "mozilla/GUniquePtr.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/GRefPtr.h"
+
+namespace mozilla {
+
+WifiScannerImpl::WifiScannerImpl() { MOZ_COUNT_CTOR(WifiScannerImpl); }
+
+WifiScannerImpl::~WifiScannerImpl() { MOZ_COUNT_DTOR(WifiScannerImpl); }
+
+nsresult WifiScannerImpl::GetAccessPointsFromWLAN(
+ AccessPointArray& aAccessPoints) {
+ RefPtr<GDBusProxy> proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync(
+ G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr,
+ "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager",
+ "org.freedesktop.NetworkManager", nullptr, nullptr));
+ if (!proxy) {
+ return NS_ERROR_FAILURE;
+ }
+
+ RefPtr<GVariant> result =
+ dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "Devices"));
+ if (!result ||
+ !g_variant_is_of_type(result, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ gsize num = g_variant_n_children(result);
+ for (gsize i = 0; i < num; i++) {
+ const char* devicePath =
+ g_variant_get_string(g_variant_get_child_value(result, i), nullptr);
+ if (!devicePath || !AddDevice(devicePath, aAccessPoints)) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ return NS_OK;
+}
+
+bool WifiScannerImpl::AddDevice(const char* aDevicePath,
+ AccessPointArray& aAccessPoints) {
+ RefPtr<GDBusProxy> proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync(
+ G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr,
+ "org.freedesktop.NetworkManager", aDevicePath,
+ "org.freedesktop.NetworkManager.Device", nullptr, nullptr));
+ if (!proxy) {
+ return false;
+ }
+
+ RefPtr<GVariant> deviceType =
+ dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "DeviceType"));
+ if (!deviceType || !g_variant_is_of_type(deviceType, G_VARIANT_TYPE_UINT32)) {
+ return false;
+ }
+
+ // http://projects.gnome.org/NetworkManager/developers/api/07/spec-07.html
+ // Refer to NM_DEVICE_TYPE_WIFI under NM_DEVICE_TYPE.
+ const uint32_t NM_DEVICE_TYPE_WIFI = 2;
+ if (g_variant_get_uint32(deviceType) != NM_DEVICE_TYPE_WIFI) {
+ // Don't probe non-wifi devices
+ return true;
+ }
+
+ proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync(
+ G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr,
+ "org.freedesktop.NetworkManager", aDevicePath,
+ "org.freedesktop.NetworkManager.Device.Wireless", nullptr, nullptr));
+ if (!proxy) {
+ return false;
+ }
+
+ RefPtr<GVariant> points =
+ dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "AccessPoints"));
+ if (!points ||
+ !g_variant_is_of_type(points, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) {
+ return false;
+ }
+
+ gsize num = g_variant_n_children(points);
+ for (gsize i = 0; i < num; i++) {
+ const char* ap =
+ g_variant_get_string(g_variant_get_child_value(points, i), nullptr);
+ if (!ap || !AddAPProperties(ap, aAccessPoints)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool WifiScannerImpl::AddAPProperties(const char* aApPath,
+ AccessPointArray& aAccessPoints) {
+ RefPtr<GDBusProxy> proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync(
+ G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr,
+ "org.freedesktop.NetworkManager", aApPath,
+ "org.freedesktop.NetworkManager.AccessPoint", nullptr, nullptr));
+ if (!proxy) {
+ return false;
+ }
+
+ RefPtr<nsWifiAccessPoint> ap = new nsWifiAccessPoint();
+
+ RefPtr<GVariant> ssid =
+ dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "Ssid"));
+ if (!ssid || !g_variant_is_of_type(ssid, G_VARIANT_TYPE_BYTESTRING)) {
+ return false;
+ }
+ const uint32_t MAX_SSID_LEN = 32;
+ gsize len = 0;
+ const char* ssidString = static_cast<const char*>(
+ g_variant_get_fixed_array(ssid, &len, sizeof(guint8)));
+ if (ssidString && len && len <= MAX_SSID_LEN) {
+ ap->setSSID(ssidString, len);
+ }
+
+ RefPtr<GVariant> hwAddress =
+ dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "HwAddress"));
+ if (!hwAddress || !g_variant_is_of_type(hwAddress, G_VARIANT_TYPE_STRING)) {
+ return false;
+ }
+ GUniquePtr<gchar> address(g_variant_dup_string(hwAddress, nullptr));
+ SetMac(address.get(), ap);
+
+ RefPtr<GVariant> st =
+ dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "Strength"));
+ if (!st || !g_variant_is_of_type(st, G_VARIANT_TYPE_BYTE)) {
+ return false;
+ }
+
+ uint8_t strength = g_variant_get_byte(st); // in %
+ int signal_strength = (strength / 2) - 100; // strength to dB
+ ap->setSignal(signal_strength);
+
+ aAccessPoints.AppendElement(ap);
+ return true;
+}
+
+bool WifiScannerImpl::SetMac(char* aHwAddress, nsWifiAccessPoint* aAp) {
+ // hwAddress format is XX:XX:XX:XX:XX:XX. Need to convert to XXXXXX format.
+ const uint32_t MAC_LEN = 6;
+ uint8_t macAddress[MAC_LEN];
+ char* savedPtr = nullptr;
+ char* token = strtok_r(aHwAddress, ":", &savedPtr);
+ for (unsigned char& macAddres : macAddress) {
+ if (!token) {
+ return false;
+ }
+ macAddres = strtoul(token, nullptr, 16);
+ token = strtok_r(nullptr, ":", &savedPtr);
+ }
+ aAp->setMac(macAddress);
+ return true;
+}
+
+} // namespace mozilla