DbusWifiScanner.cpp (5531B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include <gio/gio.h> 6 #include "DbusWifiScanner.h" 7 #include "nsWifiAccessPoint.h" 8 #include "mozilla/GUniquePtr.h" 9 #include "mozilla/RefPtr.h" 10 #include "mozilla/GRefPtr.h" 11 #include "nsAppShell.h" 12 13 namespace mozilla { 14 15 WifiScannerImpl::WifiScannerImpl() { MOZ_COUNT_CTOR(WifiScannerImpl); } 16 17 WifiScannerImpl::~WifiScannerImpl() { MOZ_COUNT_DTOR(WifiScannerImpl); } 18 19 nsresult WifiScannerImpl::GetAccessPointsFromWLAN( 20 AccessPointArray& aAccessPoints) { 21 nsAppShell::DBusConnectionCheck(); 22 RefPtr<GDBusProxy> proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync( 23 G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, 24 "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", 25 "org.freedesktop.NetworkManager", nullptr, nullptr)); 26 if (!proxy) { 27 return NS_ERROR_FAILURE; 28 } 29 30 RefPtr<GVariant> result = 31 dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "Devices")); 32 if (!result || 33 !g_variant_is_of_type(result, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) { 34 return NS_ERROR_FAILURE; 35 } 36 37 gsize num = g_variant_n_children(result); 38 for (gsize i = 0; i < num; i++) { 39 const char* devicePath = 40 g_variant_get_string(g_variant_get_child_value(result, i), nullptr); 41 if (!devicePath || !AddDevice(devicePath, aAccessPoints)) { 42 return NS_ERROR_FAILURE; 43 } 44 } 45 46 return NS_OK; 47 } 48 49 bool WifiScannerImpl::AddDevice(const char* aDevicePath, 50 AccessPointArray& aAccessPoints) { 51 nsAppShell::DBusConnectionCheck(); 52 RefPtr<GDBusProxy> proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync( 53 G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, 54 "org.freedesktop.NetworkManager", aDevicePath, 55 "org.freedesktop.NetworkManager.Device", nullptr, nullptr)); 56 if (!proxy) { 57 return false; 58 } 59 60 RefPtr<GVariant> deviceType = 61 dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "DeviceType")); 62 if (!deviceType || !g_variant_is_of_type(deviceType, G_VARIANT_TYPE_UINT32)) { 63 return false; 64 } 65 66 // http://projects.gnome.org/NetworkManager/developers/api/07/spec-07.html 67 // Refer to NM_DEVICE_TYPE_WIFI under NM_DEVICE_TYPE. 68 const uint32_t NM_DEVICE_TYPE_WIFI = 2; 69 if (g_variant_get_uint32(deviceType) != NM_DEVICE_TYPE_WIFI) { 70 // Don't probe non-wifi devices 71 return true; 72 } 73 74 nsAppShell::DBusConnectionCheck(); 75 proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync( 76 G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, 77 "org.freedesktop.NetworkManager", aDevicePath, 78 "org.freedesktop.NetworkManager.Device.Wireless", nullptr, nullptr)); 79 if (!proxy) { 80 return false; 81 } 82 83 RefPtr<GVariant> points = 84 dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "AccessPoints")); 85 if (!points || 86 !g_variant_is_of_type(points, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) { 87 return false; 88 } 89 90 gsize num = g_variant_n_children(points); 91 for (gsize i = 0; i < num; i++) { 92 const char* ap = 93 g_variant_get_string(g_variant_get_child_value(points, i), nullptr); 94 if (!ap || !AddAPProperties(ap, aAccessPoints)) { 95 return false; 96 } 97 } 98 return true; 99 } 100 101 bool WifiScannerImpl::AddAPProperties(const char* aApPath, 102 AccessPointArray& aAccessPoints) { 103 nsAppShell::DBusConnectionCheck(); 104 RefPtr<GDBusProxy> proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync( 105 G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, 106 "org.freedesktop.NetworkManager", aApPath, 107 "org.freedesktop.NetworkManager.AccessPoint", nullptr, nullptr)); 108 if (!proxy) { 109 return false; 110 } 111 112 RefPtr<nsWifiAccessPoint> ap = new nsWifiAccessPoint(); 113 114 RefPtr<GVariant> ssid = 115 dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "Ssid")); 116 if (!ssid || !g_variant_is_of_type(ssid, G_VARIANT_TYPE_BYTESTRING)) { 117 return false; 118 } 119 const uint32_t MAX_SSID_LEN = 32; 120 gsize len = 0; 121 const char* ssidString = static_cast<const char*>( 122 g_variant_get_fixed_array(ssid, &len, sizeof(guint8))); 123 if (ssidString && len && len <= MAX_SSID_LEN) { 124 ap->setSSID(ssidString, len); 125 } 126 127 RefPtr<GVariant> hwAddress = 128 dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "HwAddress")); 129 if (!hwAddress || !g_variant_is_of_type(hwAddress, G_VARIANT_TYPE_STRING)) { 130 return false; 131 } 132 GUniquePtr<gchar> address(g_variant_dup_string(hwAddress, nullptr)); 133 SetMac(address.get(), ap); 134 135 RefPtr<GVariant> st = 136 dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "Strength")); 137 if (!st || !g_variant_is_of_type(st, G_VARIANT_TYPE_BYTE)) { 138 return false; 139 } 140 141 uint8_t strength = g_variant_get_byte(st); // in % 142 int signal_strength = (strength / 2) - 100; // strength to dB 143 ap->setSignal(signal_strength); 144 145 aAccessPoints.AppendElement(ap); 146 return true; 147 } 148 149 bool WifiScannerImpl::SetMac(char* aHwAddress, nsWifiAccessPoint* aAp) { 150 // hwAddress format is XX:XX:XX:XX:XX:XX. Need to convert to XXXXXX format. 151 const uint32_t MAC_LEN = 6; 152 uint8_t macAddress[MAC_LEN]; 153 char* savedPtr = nullptr; 154 char* token = strtok_r(aHwAddress, ":", &savedPtr); 155 for (unsigned char& macAddres : macAddress) { 156 if (!token) { 157 return false; 158 } 159 macAddres = strtoul(token, nullptr, 16); 160 token = strtok_r(nullptr, ":", &savedPtr); 161 } 162 aAp->setMac(macAddress); 163 return true; 164 } 165 166 } // namespace mozilla