From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1PzxD3-0004nB-53 for garchives@archives.gentoo.org; Wed, 16 Mar 2011 20:20:52 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 65E881C020; Wed, 16 Mar 2011 20:20:37 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id BB7651C020 for ; Wed, 16 Mar 2011 20:20:36 +0000 (UTC) Received: from pelican.gentoo.org (unknown [66.219.59.40]) (using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id D1E171BC1E7 for ; Wed, 16 Mar 2011 20:20:35 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by pelican.gentoo.org (Postfix) with ESMTP id 387878006A for ; Wed, 16 Mar 2011 20:20:35 +0000 (UTC) From: "Nirbheek Chauhan" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Nirbheek Chauhan" Message-ID: Subject: [gentoo-commits] proj/gnome:master commit in: gnome-base/gnome-shell/, net-misc/networkmanager/, ... X-VCS-Repository: proj/gnome X-VCS-Files: gnome-base/gnome-shell/files/gnome-shell-experimental-nm-applet-1.5.patch gnome-base/gnome-shell/gnome-shell-9999.ebuild net-misc/networkmanager/files/networkmanager-0.8.996-fix-introspection.patch net-misc/networkmanager/networkmanager-0.8.996-r1.ebuild net-misc/networkmanager/networkmanager-0.8.996.ebuild X-VCS-Directories: gnome-base/gnome-shell/ net-misc/networkmanager/ net-misc/networkmanager/files/ gnome-base/gnome-shell/files/ X-VCS-Committer: nirbheek X-VCS-Committer-Name: Nirbheek Chauhan X-VCS-Revision: c9fdf24db6db05d9cb04e78c775faa3e5c8fd5df Date: Wed, 16 Mar 2011 20:20:35 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: X-Archives-Hash: 534630358f95b73cad87b9bafd353389 commit: c9fdf24db6db05d9cb04e78c775faa3e5c8fd5df Author: Nirbheek Chauhan gentoo org> AuthorDate: Wed Mar 16 20:19:21 2011 +0000 Commit: Nirbheek Chauhan gentoo org> CommitDate: Wed Mar 16 20:19:21 2011 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/gnome.git;a=3D= commit;h=3Dc9fdf24d gnome-base/gnome-shell: nm-applet patch is now upstream * Update networkmanager and gnome-shell deps --- .../gnome-shell-experimental-nm-applet-1.5.patch | 3446 --------------= ------ gnome-base/gnome-shell/gnome-shell-9999.ebuild | 22 +- .../networkmanager-0.8.996-fix-introspection.patch | 51 + ...996.ebuild =3D> networkmanager-0.8.996-r1.ebuild} | 4 + 4 files changed, 62 insertions(+), 3461 deletions(-) diff --git a/gnome-base/gnome-shell/files/gnome-shell-experimental-nm-app= let-1.5.patch b/gnome-base/gnome-shell/files/gnome-shell-experimental-nm-= applet-1.5.patch deleted file mode 100644 index d32aca4..0000000 --- a/gnome-base/gnome-shell/files/gnome-shell-experimental-nm-applet-1.5= .patch +++ /dev/null @@ -1,3446 +0,0 @@ -From 1bf9b9694338ba917db07d2bf75146dba6a80054 Mon Sep 17 00:00:00 2001 -From: Giovanni Campagna -Date: Tue, 25 Jan 2011 22:08:12 +0100 -Subject: [PATCH] Status area: add NetworkManager indicator - -Adds an implementation of nm-applet in javascript. Uses the new -introspection from NetworkManager, and temporarily requires -nm-applet to be running for the secret service. -Features a renewed interface, with each device controllable through -a switch, which if toggled off disconnects, and if toggled on -connects to the most recently used valid connection. More esoteric -features like creation of ad-hoc networks have been moved to the -control center panel. - -https://bugzilla.gnome.org/show_bug.cgi?id=3D621707 ---- - data/theme/gnome-shell.css | 8 + - js/Makefile.am | 2 + - js/misc/modemManager.js | 219 +++++ - js/misc/util.js | 80 ++ - js/ui/panel.js | 7 + - js/ui/status/network.js | 2048 ++++++++++++++++++++++++++++++++= +++++++ - src/Makefile.am | 5 +- - src/shell-mobile-providers.c | 816 ++++++++++++++++ - src/shell-mobile-providers.h | 96 ++ - tools/build/gnome-shell.modules | 17 + - 10 files changed, 3297 insertions(+), 1 deletions(-) - create mode 100644 js/misc/modemManager.js - create mode 100644 js/ui/status/network.js - create mode 100644 src/shell-mobile-providers.c - create mode 100644 src/shell-mobile-providers.h - -diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css -index 7d9f011..5d7eea2 100644 ---- a/data/theme/gnome-shell.css -+++ b/data/theme/gnome-shell.css -@@ -160,6 +160,14 @@ StTooltip StLabel { - spacing: .5em; - } -=20 -+.popup-inactive-menu-item { -+ font-style: italic; -+} -+ -+.popup-subtitle-menu-item { -+ font-weight: bold; -+} -+ - .popup-menu-icon { - icon-size: 1.14em; - } -diff --git a/js/Makefile.am b/js/Makefile.am -index 55bb111..a085bfc 100644 ---- a/js/Makefile.am -+++ b/js/Makefile.am -@@ -8,6 +8,7 @@ nobase_dist_js_DATA =3D \ - misc/format.js \ - misc/gnomeSession.js \ - misc/history.js \ -+ misc/modemManager.js \ - misc/params.js \ - misc/util.js \ - perf/core.js \ -@@ -50,6 +51,7 @@ nobase_dist_js_DATA =3D \ - ui/statusMenu.js \ - ui/status/accessibility.js \ - ui/status/keyboard.js \ -+ ui/status/network.js \ - ui/status/power.js \ - ui/status/volume.js \ - ui/status/bluetooth.js \ -diff --git a/js/misc/modemManager.js b/js/misc/modemManager.js -new file mode 100644 -index 0000000..5b2754b ---- /dev/null -+++ b/js/misc/modemManager.js -@@ -0,0 +1,219 @@ -+// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- -+ -+const DBus =3D imports.dbus; -+const Lang =3D imports.lang; -+const Shell =3D imports.gi.Shell; -+const Signals =3D imports.signals; -+ -+// The following are not the complete interfaces, just the methods we n= eed -+// (or may need in the future) -+ -+const ModemGsmNetworkInterface =3D { -+ name: 'org.freedesktop.ModemManager.Modem.Gsm.Network', -+ methods: [ -+ { name: 'GetRegistrationInfo', inSignature: '', outSignature: '= uss' }, -+ { name: 'GetSignalQuality', inSignature: '', outSignature: 'u' = } -+ ], -+ properties: [ -+ { name: 'AccessTechnology', signature: 'u', access: 'read' } -+ ], -+ signals: [ -+ { name: 'SignalQuality', inSignature: 'u' }, -+ { name: 'RegistrationInfo', inSignature: 'uss' } -+ ] -+}; -+const ModemGsmNetworkProxy =3D DBus.makeProxyClass(ModemGsmNetworkInter= face); -+ -+const ModemCdmaInterface =3D { -+ name: 'org.freedesktop.ModemManager.Modem.Cdma', -+ methods: [ -+ { name: 'GetSignalQuality', inSignature: '', outSignature: 'u' = }, -+ { name: 'GetServingSystem', inSignature: '', outSignature: 'usu= ' } -+ ], -+ signals: [ -+ { name: 'SignalQuality', inSignature: 'u' } -+ ] -+}; -+const ModemCdmaProxy =3D DBus.makeProxyClass(ModemCdmaInterface); -+ -+let _providersTable; -+function _getProvidersTable() { -+ if (_providersTable) -+ return _providersTable; -+ let [providers, countryCodes] =3D Shell.mobile_providers_parse(); -+ return _providersTable =3D providers; -+} -+ -+function _findProviderForMCCMNC(needle) { -+ let table =3D _getProvidersTable(); -+ let needlemcc =3D needle.substring(0, 3); -+ let needlemnc =3D needle.substring(3, needle.length); -+ -+ let name2, name3; -+ for (let iter in table) { -+ let providers =3D table[value]; -+ -+ /* Search through each country's providers */ -+ for (let i =3D 0; i < providers.length; i++) { -+ let provider =3D providers[i]; -+ -+ /* Search through MCC/MNC list */ -+ let list =3D provider.get_gsm_mcc_mnc(); -+ for (let j =3D 0; j < list.length; j++) { -+ let mccmnc =3D list[j]; -+ -+ /* Match both 2-digit and 3-digit MNC; prefer a -+ * 3-digit match if found, otherwise a 2-digit one. -+ */ -+ if (mccmnc.mcc !=3D needlemcc) -+ continue; /* MCC was wrong */ -+ -+ if (!name3 && needle.length =3D=3D 6 && needlemnc =3D=3D mccmnc.mnc) -+ name3 =3D provider.name; -+ -+ if (!name2 && needlemnc.substring(0, 2) =3D=3D mcc.mnc.substring(0, 2= )) -+ name2 =3D provider.name; -+ -+ if (name2 && name3) -+ break; -+ } -+ } -+ } -+ -+ return name3 || name2 || null; -+} -+ -+function _findProviderForSid(sid) { -+ if (sid =3D=3D 0) -+ return null; -+ -+ let table =3D _getProvidersTable(); -+ -+ /* Search through each country */ -+ for (let iter in table) { -+ let providers =3D table[iter]; -+ -+ /* Search through each country's providers */ -+ for (let i =3D 0; i < providers.length; i++) { -+ let provider =3D providers[i]; -+ let cdma_sid =3D provider.get_cdma_sid(); -+ -+ /* Search through CDMA SID list */ -+ for (let j =3D 0; j < cdma_sid.length; j++) { -+ if (cmda_sid[j] =3D=3D sid) -+ return provider.name; -+ } -+ } -+ } -+ -+ return null; -+} -+ -+function ModemGsm() { -+ this._init.apply(this, arguments); -+} -+ -+ModemGsm.prototype =3D { -+ _init: function(path) { -+ this._proxy =3D new ModemGsmNetworkProxy(DBus.system, 'org.free= desktop.ModemManager', path); -+ -+ this.signal_quality =3D 0; -+ this.operator_name =3D null; -+ -+ // Code is duplicated because the function have different signa= tures -+ this._proxy.connect('SignalQuality', Lang.bind(this, function(p= roxy, quality) { -+ this.signal_quality =3D quality; -+ this.emit('notify::signal-quality'); -+ })); -+ this._proxy.connect('RegistrationInfo', Lang.bind(this, functio= n(proxy, status, code, name) { -+ this.operator_name =3D this._findOperatorName(name, code); -+ this.emit('notify::operator-name'); -+ })); -+ this._proxy.GetRegistrationInfoRemote(Lang.bind(this, function(= result, err) { -+ if (err) { -+ log(err); -+ return; -+ } -+ -+ let [status, code, name] =3D result; -+ this.operator_name =3D this._findOperatorName(name, code); -+ this.emit('notify::operator-name'); -+ })); -+ this._proxy.GetSignalQualityRemote(Lang.bind(this, function(res= ult, err) { -+ if (err) { -+ // it will return an error if the device is not connect= ed -+ this.signal_quality =3D 0; -+ } else { -+ let [quality] =3D result; -+ this.signal_quality =3D quality; -+ } -+ this.emit('notify::signal-quality'); -+ })); -+ }, -+ -+ _findOperatorName: function(name, opCode) { -+ if (name.length !=3D 0 && (name.length > 6 || name.length < 5))= { -+ // this looks like a valid name, i.e. not an MCCMNC (that s= ome -+ // devices return when not yet connected -+ return name; -+ } -+ let needle; -+ if (name.length =3D=3D 0 && opCode) -+ needle =3D opCode; -+ else if (name.length =3D=3D 6 || name.length =3D=3D 5) -+ needle =3D name; -+ else // nothing to search -+ return null; -+ -+ return _findProviderForMCCMNC(needle); -+ } -+} -+Signals.addSignalMethods(ModemGsm.prototype); -+ -+function ModemCdma() { -+ this._init.apply(this, arguments); -+} -+ -+ModemCdma.prototype =3D { -+ _init: function(path) { -+ this._proxy =3D new ModemCdmaProxy(DBus.system, 'org.freedeskto= p.ModemManager', path); -+ -+ this.signal_quality =3D 0; -+ this.operator_name =3D null; -+ this._proxy.connect('SignalQuality', Lang.bind(this, function(q= uality) { -+ this.signal_quality =3D quality; -+ this.emit('notify::signal-quality'); -+ -+ // receiving this signal means the device got activated -+ // and we can finally call GetServingSystem -+ if (this.operator_name =3D=3D null) -+ this._refreshServingSystem(); -+ })); -+ this._proxy.GetSignalQualityRemote(Lang.bind(this, function(res= ult, err) { -+ if (err) { -+ // it will return an error if the device is not connect= ed -+ this.signal_quality =3D 0; -+ } else { -+ let [quality] =3D result; -+ this.signal_quality =3D quality; -+ } -+ this.emit('notify::signal-quality'); -+ })); -+ }, -+ _refreshServingSystem: function() { -+ this._proxy.GetServingSystemRemote(Lang.bind(this, function(res= ult, err) { -+ if (err) { -+ // it will return an error if the device is not connect= ed -+ this.operator_name =3D null; -+ } else { -+ let [bandClass, band, id] =3D result; -+ if (name.length > 0) -+ this.operator_name =3D _findProviderForSid(id); -+ else -+ this.operator_name =3D null; -+ } -+ this.emit('notify::operator-name'); -+ })); -+ } -+}; -+Signals.addSignalMethods(ModemCdma.prototype); -diff --git a/js/misc/util.js b/js/misc/util.js -index e2ec2c1..ab430c8 100644 ---- a/js/misc/util.js -+++ b/js/misc/util.js -@@ -178,3 +178,83 @@ function killall(processName) { - logError(e, 'Failed to kill ' + processName); - } - } -+ -+// This was ported from network-manager-applet -+// Copyright 2007 - 2011 Red Hat, Inc. -+// Author: Dan Williams -+ -+const _IGNORED_WORDS =3D [ -+ 'Semiconductor', -+ 'Components', -+ 'Corporation', -+ 'Communications', -+ 'Company', -+ 'Corp.', -+ 'Corp', -+ 'Co.', -+ 'Inc.', -+ 'Inc', -+ 'Incorporated', -+ 'Ltd.', -+ 'Limited.', -+ 'Intel?', -+ 'chipset', -+ 'adapter', -+ '[hex]', -+ 'NDIS', -+ 'Module' -+]; -+ -+const _IGNORED_PHRASES =3D [ -+ 'Multiprotocol MAC/baseband processor', -+ 'Wireless LAN Controller', -+ 'Wireless LAN Adapter', -+ 'Wireless Adapter', -+ 'Network Connection', -+ 'Wireless Cardbus Adapter', -+ 'Wireless CardBus Adapter', -+ '54 Mbps Wireless PC Card', -+ 'Wireless PC Card', -+ 'Wireless PC', -+ 'PC Card with XJACK(r) Antenna', -+ 'Wireless cardbus', -+ 'Wireless LAN PC Card', -+ 'Technology Group Ltd.', -+ 'Communication S.p.A.', -+ 'Business Mobile Networks BV', -+ 'Mobile Broadband Minicard Composite Device', -+ 'Mobile Communications AB', -+ '(PC-Suite Mode)' -+]; -+ -+function fixupPCIDescription(desc) { -+ desc.replace('[_,]', ' '); -+ -+ /* Attempt to shorten ID by ignoring certain phrases */ -+ for (let i =3D 0; i < _IGNORED_PHRASES.length; i++) { -+ let item =3D _IGNORED_PHRASES[i]; -+ let pos =3D desc.indexOf(item); -+ if (pos !=3D -1) { -+ let before =3D desc.substring(0, pos); -+ let after =3D desc.substring(pos + item.length, desc.length= ); -+ desc =3D before + after; -+ } -+ } -+ -+ /* Attmept to shorten ID by ignoring certain individual words */ -+ let words =3D desc.split(' '); -+ let out =3D ''; -+ for (let i =3D 0; i < words; i++) { -+ let item =3D words[i]; -+ -+ // skip empty items (that come out from consecutive spaces) -+ if (item.length =3D=3D 0) -+ continue; -+ -+ if (_IGNORED_WORDS.indexOf(item) =3D=3D -1) { -+ out +=3D ' ' + item; -+ } -+ } -+ -+ return out; -+} -\ No newline at end of file -diff --git a/js/ui/panel.js b/js/ui/panel.js -index c08c3e8..adcd148 100644 ---- a/js/ui/panel.js -+++ b/js/ui/panel.js -@@ -47,6 +47,13 @@ const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION =3D { - if (Config.HAVE_BLUETOOTH) - STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['bluetooth'] =3D imports.ui= .status.bluetooth.Indicator; -=20 -+try { -+ STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['network'] =3D imports.ui.s= tatus.network.NMApplet; -+} catch(e) { -+ STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['network'] =3D undefined; -+ log('NMApplet is not supported. It is possible that your NetworkMan= ager version is too old'); -+} -+ - // To make sure the panel corners blend nicely with the panel, - // we draw background and borders the same way, e.g. drawing - // them as filled shapes from the outside inwards instead of -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -new file mode 100644 -index 0000000..ac8e3d0 ---- /dev/null -+++ b/js/ui/status/network.js -@@ -0,0 +1,2048 @@ -+// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- -+const ByteArray =3D imports.byteArray; -+const DBus =3D imports.dbus; -+const GLib =3D imports.gi.GLib; -+const GObject =3D imports.gi.GObject; -+const Lang =3D imports.lang; -+const Mainloop =3D imports.mainloop; -+const NetworkManager =3D imports.gi.NetworkManager; -+const NMClient =3D imports.gi.NMClient; -+const Shell =3D imports.gi.Shell; -+const Signals =3D imports.signals; -+const St =3D imports.gi.St; -+ -+const Main =3D imports.ui.main; -+const PanelMenu =3D imports.ui.panelMenu; -+const PopupMenu =3D imports.ui.popupMenu; -+const MessageTray =3D imports.ui.messageTray; -+const ModemManager =3D imports.misc.modemManager; -+const Util =3D imports.misc.util; -+ -+const Gettext =3D imports.gettext.domain('gnome-shell'); -+const _ =3D Gettext.gettext; -+ -+const NMConnectionCategory =3D { -+ WIRED: 'wired', -+ WIRELESS: 'wireless', -+ WWAN: 'wwan', -+ VPN: 'vpn' -+}; -+ -+// small optimization, to avoid using [] all the time -+const NM80211Mode =3D NetworkManager['80211Mode']; -+const NM80211ApFlags =3D NetworkManager['80211ApFlags']; -+ -+function macToArray(string) { -+ return string.split(':').map(function(el) { -+ return parseInt(el, 16); -+ }); -+} -+ -+function macCompare(one, two) { -+ for (let i =3D 0; i < 6; i++) { -+ if (one[i] !=3D two[i]) -+ return false; -+ } -+ return true; -+} -+ -+function ssidCompare(one, two) { -+ if (!one || !two) -+ return false; -+ if (one.length !=3D two.length) -+ return false; -+ for (let i =3D 0; i < one.length; i++) { -+ if (one[i] !=3D two[i]) -+ return false; -+ } -+ return true; -+} -+ -+// shared between NMNetworkMenuItem and NMDeviceWWAN -+function signalToIcon(value) { -+ if (value > 80) -+ return 'excellent'; -+ if (value > 55) -+ return 'good'; -+ if (value > 30) -+ return 'ok'; -+ if (value > 5) -+ return 'weak'; -+ return 'none'; -+} -+ -+// shared between NMNetworkMenuItem and NMDeviceWireless -+function getApSecurityType(accessPoint) { -+ // XXX: have this checked by someone familiar with IEEE 802.1x -+ -+ let flags =3D accessPoint.flags; -+ let wpa_flags =3D accessPoint.wpa_flags; -+ let rsn_flags =3D accessPoint.rsn_flags; -+ if ( !(flags & NM80211ApFlags.PRIVACY) -+ && (wpa_flags =3D=3D NM80211ApSecurityFlags.NONE) -+ && (rsn_flags =3D=3D NM80211ApSecurityFlags.NONE)) -+ return 0; -+ else if ( (flags & NM80211ApFlags.PRIVACY) -+ && (wpa_flags =3D=3D NM80211ApSecurityFlags.NONE) -+ && (rsn_flags =3D=3D NM80211ApSecurityFlags.NONE)) -+ return 1; -+ else if ( !(flags & NM80211ApFlags.PRIVACY) -+ && (wpa_flags !=3D NM80211ApSecurity.NONE) -+ && (rsn_flags !=3D NM80211ApSecurity.NONE)) -+ return 2; -+ else -+ return 3; -+} -+ -+function sortAccessPoints(accessPoints) { -+ return accessPoints.sort(function (one, two) { -+ return two.strength - one.strength; -+ }); -+} -+ -+function getDeviceDescription(device) { -+ let dev_product =3D device.get_product(); -+ let dev_vendor =3D device.get_vendor(); -+ if (!dev_product || !dev_vendor) -+ return null; -+ -+ let product =3D Util.fixupPCIDescription(dev_product); -+ let vendor =3D Util.fixupPCIDescription(dev_vendor); -+ let out =3D ''; -+ -+ /* Another quick hack; if all of the fixed up vendor string -+ * is found in product, ignore the vendor. -+ */ -+ if (product.indexOf(vendor) =3D=3D -1) -+ out +=3D vendor + ' '; -+ out +=3D product; -+ -+ return out; -+} -+ -+function NMNetworkMenuItem() { -+ this._init.apply(this, arguments); -+} -+ -+NMNetworkMenuItem.prototype =3D { -+ __proto__: PopupMenu.PopupImageMenuItem.prototype, -+ -+ _init: function(accessPoints, title, params) { -+ accessPoints =3D sortAccessPoints(accessPoints); -+ this.bestAP =3D accessPoints[0]; -+ -+ let ssid =3D this.bestAP.get_ssid(); -+ title =3D title || NetworkManager.utils_ssid_to_utf8(ssid) || _= (""); -+ -+ PopupMenu.PopupImageMenuItem.prototype._init.call(this, title, = this._getIcon(), params); -+ -+ this._accessPoints =3D [ ]; -+ for (let i =3D 0; i < accessPoints.length; i++) { -+ let ap =3D accessPoints[i]; -+ // need a wrapper object here, because the access points ca= n be shared -+ // between many NMNetworkMenuItems -+ let apObj =3D { -+ ap: ap, -+ updateId: ap.connect('notify::strength', Lang.bind(this= , this._updated)) -+ }; -+ this._accessPoints.push(apObj); -+ } -+ }, -+ -+ _updated: function(ap, strength) { -+ if (strength > this.bestAP.strength) -+ this.bestAP =3D ap; -+ -+ this.setIcon(this._getIcon()); -+ }, -+ -+ _getIcon: function() { -+ return 'network-wireless-signal-' + signalToIcon(this.bestAP.st= rength); -+ }, -+ -+ updateAccessPoints: function(accessPoints) { -+ for (let i =3D 0; i < this._accessPoints.length; i++) { -+ let apObj =3D this._accessPoints[i]; -+ apObj.ap.disconnect(apObj.updateId); -+ apObj.updateId =3D 0; -+ } -+ -+ accessPoints =3D sortAccessPoints(accessPoints); -+ this.bestAP =3D accessPoints[0]; -+ this._accessPoints =3D [ ]; -+ for (let i =3D 0; i < accessPoints; i++) { -+ let ap =3D accessPoints[i]; -+ let apObj =3D { -+ ap: ap, -+ updateId: ap.connect('notify::strength', Lang.bind(this= , this._updated)) -+ }; -+ this._accessPoints.push(apObj); -+ } -+ }, -+ -+ destroy: function() { -+ for (let i =3D 0; i < this._accessPoints.length; i++) { -+ let apObj =3D this._accessPoints[i]; -+ apObj.ap.disconnect(apObj.updateId); -+ apObj.updateId =3D 0; -+ } -+ -+ PopupMenu.PopupImageMenuItem.prototype.destroy.call(this); -+ } -+}; -+ -+function NMDeviceTitleMenuItem() { -+ this._init.apply(this, arguments); -+} -+ -+NMDeviceTitleMenuItem.prototype =3D { -+ __proto__: PopupMenu.PopupBaseMenuItem.prototype, -+ -+ _init: function(description, params) { -+ PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params); -+ -+ this._descriptionLabel =3D new St.Label({ text: description, -+ style_class: 'popup-sub= title-menu-item' -+ }); -+ this.addActor(this._descriptionLabel); -+ -+ this._statusBin =3D new St.Bin({ x_align: St.Align.END }); -+ this.addActor(this._statusBin, { align: St.Align.END }); -+ -+ this._statusLabel =3D new St.Label({ text: '', -+ style_class: 'popup-inactive= -menu-item' -+ }); -+ this._switch =3D new PopupMenu.Switch(false); -+ this._statusBin.child =3D this._switch.actor; -+ }, -+ -+ setStatus: function(text) { -+ if (text) { -+ this._statusLabel.text =3D text; -+ this._statusBin.child =3D this._statusLabel; -+ this.actor.reactive =3D false; -+ this.actor.can_focus =3D false; -+ } else { -+ this._statusBin.child =3D this._switch.actor; -+ this.actor.reactive =3D true; -+ this.actor.can_focus =3D true; -+ } -+ }, -+ -+ activate: function(event) { -+ if (this._switch.actor.mapped) { -+ this._switch.toggle(); -+ this.emit('toggled', this._switch.state); -+ } -+ -+ PopupMenu.PopupBaseMenuItem.prototype.activate.call(this, event= ); -+ }, -+ -+ get state() { -+ return this._switch.state; -+ }, -+ -+ setToggleState: function(newval) { -+ this._switch.setToggleState(newval); -+ } -+}; -+ -+function NMWiredSectionTitleMenuItem() { -+ this._init.apply(this, arguments); -+} -+ -+NMWiredSectionTitleMenuItem.prototype =3D { -+ __proto__: NMDeviceTitleMenuItem.prototype, -+ -+ updateForDevice: function(device) { -+ if (device) { -+ this._device =3D device; -+ this.setStatus(device.getStatusLabel()); -+ this.setToggleState(device.connected); -+ } else -+ this.setStatus(''); -+ }, -+ -+ activate: function(event) { -+ NMDeviceTitleMenuItem.prototype.activate.call(this, event); -+ -+ if (!this._device) { -+ log('Section title activated when there is more than one de= vice, should be non reactive'); -+ return; -+ } -+ -+ if (this._switch.state) -+ this._device.activate(); -+ else -+ this._device.deactivate(); -+ } -+}; -+ -+function NMWirelessSectionTitleMenuItem() { -+ this._init.apply(this, arguments); -+} -+ -+NMWirelessSectionTitleMenuItem.prototype =3D { -+ __proto__: NMDeviceTitleMenuItem.prototype, -+ -+ _init: function(client, property, title, params) { -+ NMDeviceTitleMenuItem.prototype._init.call(this, title, params)= ; -+ -+ this._client =3D client; -+ this._property =3D property + '_enabled'; -+ this._propertyHardware =3D property + '_hardware_enabled'; -+ this._setEnabledFunc =3D property + '_set_enabled'; -+ -+ this._client.connect('notify::' + property + '-enabled', Lang.b= ind(this, this._propertyChanged)); -+ this._client.connect('notify::' + property + '-hardware-enabled= ', Lang.bind(this, this._propertyChanged)); -+ -+ this._propertyChanged(); -+ }, -+ -+ updateForDevice: function(device) { -+ // we show the switch -+ // - if there not just one device -+ // - if the switch is off -+ // - if the device is activated or disconnected -+ if (device && this._softwareEnabled && this._hardwareEnabled) { -+ let text =3D device.getStatusLabel(); -+ this.setStatus(text); -+ } else -+ this.setStatus(null); -+ }, -+ -+ activate: function(event) { -+ NMDeviceTitleMenuItem.prototype.activate.call(this, event); -+ -+ this._client[this._setEnabledFunc](this._switch.state); -+ }, -+ -+ _propertyChanged: function() { -+ this._softwareEnabled =3D this._client[this._property]; -+ this._hardwareEnabled =3D this._client[this._propertyHardware]; -+ -+ let enabled =3D this._softwareEnabled && this._hardwareEnabled; -+ this.setToggleState(enabled); -+ if (!this._hardwareEnabled) -+ /* Translators: this indicates that wireless or wwan is dis= abled by hardware killswitch */ -+ this.setStatus(_("disabled")); -+ -+ this.emit('enabled-changed', enabled); -+ } -+}; -+ -+function NMDevice() { -+ throw new TypeError('Instantanting abstract class NMDevice'); -+} -+ -+NMDevice.prototype =3D { -+ _init: function(client, device, connections) { -+ this.device =3D device; -+ if (device) { -+ this.device._delegate =3D this; -+ this._stateChangedId =3D this.device.connect('state-changed= ', Lang.bind(this, this.deviceStateChanged)); -+ } else -+ this._stateChangedId =3D 0; -+ -+ // protected -+ this._client =3D client; -+ this._connections =3D [ ]; -+ for (let i =3D 0; i < connections.length; i++) { -+ if (!connections[i]._uuid) -+ continue; -+ if (!this.connectionValid(connections[i])) -+ continue; -+ // record the connection -+ let obj =3D { -+ connection: connections[i], -+ name: connections[i]._name, -+ uuid: connections[i]._uuid, -+ timestamp: connections[i]._timestamp, -+ }; -+ this._connections.push(obj); -+ } -+ this._connections.sort(function(one, two) { -+ return two.timestamp - one.timestamp; -+ }); -+ this._activeConnection =3D null; -+ this._activeConnectionItem =3D null; -+ this._autoConnectionItem =3D null; -+ this._onlyOfCategory =3D false; -+ -+ if (this.device) { -+ this.statusItem =3D new NMDeviceTitleMenuItem(this.device._= description); -+ this._statusChanged =3D this.statusItem.connect('toggled', = Lang.bind(this, function(item, state) { -+ if (state) -+ this.activate(); -+ else -+ this.deactivate(); -+ this.emit('enabled-changed'); -+ })); -+ } -+ this.section =3D new PopupMenu.PopupMenuSection(); -+ -+ this._createSection(); -+ }, -+ -+ destroy: function() { -+ if (this.device) -+ this.device._delegate =3D null; -+ -+ if (this._stateChangedId) { -+ // Need to go through GObject.Object.prototype because -+ // nm_device_disconnect conflicts with g_signal_disconnect -+ GObject.Object.prototype.disconnect.call(this.device, this.= _stateChangedId); -+ this._stateChangedId =3D 0; -+ } -+ -+ this._clearSection(); -+ if (this.titleItem) -+ this.titleItem.destroy(); -+ this.section.destroy(); -+ }, -+ -+ deactivate: function() { -+ this.device.disconnect(null); -+ }, -+ -+ activate: function() { -+ if (this._activeConnection) -+ // nothing to do -+ return; -+ -+ // pick the most recently used connection and connect to that -+ // or if no connections ever set, create an automatic one -+ if (this._connections.length > 0) { -+ this._client.activate_connection(this._connections[0].conne= ction.path, this.device, null, null); -+ } else if (this._autoConnectionName) { -+ let connection =3D this._createAutomaticConnection(); -+ this._client.add_and_activate_connection(connection, this.d= evice, null, null); -+ } -+ }, -+ -+ get connected() { -+ return this.device.state =3D=3D NetworkManager.DeviceState.ACTI= VATED; -+ }, -+ -+ setActiveConnection: function(activeConnection) { -+ if (activeConnection =3D=3D this._activeConnection) -+ // nothing to do -+ return; -+ -+ // remove any UI -+ if (this._activeConnectionItem) { -+ this._activeConnectionItem.destroy(); -+ this._activeConnectionItem =3D null; -+ } -+ -+ this._activeConnection =3D activeConnection; -+ -+ this._clearSection(); -+ this._createSection(); -+ }, -+ -+ checkConnection: function(connection) { -+ let exists =3D this._findConnection(connection) !=3D -1; -+ let valid =3D this.connectionValid(connection); -+ if (exists && !valid) -+ this.removeConnection(connection); -+ else if (!exists && valid) -+ this.addConnection(connection); -+ }, -+ -+ addConnection: function(connection) { -+ // record the connection -+ let obj =3D { -+ connection: connection, -+ name: connection._name, -+ uuid: connection._uuid, -+ timestamp: connection._timestamp, -+ }; -+ this._connections.push(obj); -+ this._connections.sort(function(one, two) { -+ return two.timestamp - one.timestamp; -+ }); -+ -+ this._clearSection(); -+ this._createSection(); -+ }, -+ -+ removeConnection: function(connection) { -+ if (!connection._uuid) { -+ log('Cannot remove a connection without an UUID'); -+ return; -+ } -+ let pos =3D this._findConnection(connection._uuid); -+ if (pos =3D=3D -1) { -+ // this connection was never added, nothing to do here -+ return; -+ } -+ -+ let obj =3D this._connections[pos]; -+ if (obj.item) -+ obj.item.destroy(); -+ this._connections.splice(pos, 1); -+ -+ if (this._connections.length =3D=3D 0) { -+ // We need to show the automatic connection again -+ this._clearSection(); -+ this._createSection(); -+ } -+ }, -+ -+ connectionValid: function(connection) { -+ throw new TypeError('Invoking pure virtual function NMDevice.co= nnectionValid'); -+ }, -+ -+ setEnabled: function(enabled) { -+ // do nothing by default, we want to keep the conneciton list v= isible -+ // in the majority of cases (wired, wwan, vpn) -+ }, -+ -+ getStatusLabel: function() { -+ switch(this.device.state) { -+ case NetworkManager.DeviceState.DISCONNECTED: -+ case NetworkManager.DeviceState.ACTIVATED: -+ return null; -+ case NetworkManager.DeviceState.PREPARE: -+ case NetworkManager.DeviceState.CONFIG: -+ case NetworkManager.DeviceState.IP_CONFIG: -+ return _("connecting..."); -+ case NetworkManager.DeviceState.NEED_AUTH: -+ /* Translators: this is for network connections that requir= e some kind of key or password */ -+ return _("authentication required"); -+ case NetworkManager.DeviceState.UNAVAILABLE: -+ // we don't check if the carrier property is actually false= , as that causes race -+ // conditions if state is changed before the new carrier va= lue is picked by libnm-glib -+ if (this.device.capabilities & NetworkManager.DeviceCapabil= ities.CARRIER_DETECT) -+ /* Translators: this is for wired network devices that = are physically disconnected */ -+ return _("cable unplugged"); -+ else -+ /* Translators: this is for a network device that canno= t be activated (for example it -+ is disabled by rfkill, or it has no coverage */ -+ return _("unavailable"); -+ case NetworkManager.DeviceState.FAILED: -+ return _("connection failed"); -+ default: -+ log('Device state invalid, is %d'.format(this.device.state)= ); -+ return 'invalid'; -+ } -+ }, -+ -+ // protected -+ _createAutomaticConnection: function() { -+ throw new TypeError('Invoking pure virtual function NMDevice.cr= eateAutomaticConnection'); -+ }, -+ -+ _findConnection: function(uuid) { -+ for (let i =3D 0; i < this._connections.length; i++) { -+ let obj =3D this._connections[i]; -+ if (obj.uuid =3D=3D uuid) -+ return i; -+ } -+ return -1; -+ }, -+ -+ _clearSection: function() { -+ // Clear everything -+ this.section.removeAll(); -+ this._autoConnectionItem =3D null; -+ this._activeConnectionItem =3D null; -+ for (let i =3D 0; i < this._connections.length; i++) { -+ this._connections[i].item =3D null; -+ } -+ }, -+ -+ _shouldShowConnectionList: function() { -+ return (this.device.state =3D=3D NetworkManager.DeviceState.DIS= CONNECTED || -+ this.device.state =3D=3D NetworkManager.DeviceState.ACT= IVATED); -+ }, -+ -+ _createSection: function() { -+ if (!this._shouldShowConnectionList()) -+ return; -+ -+ if (this._activeConnection) { -+ this._createActiveConnectionItem(); -+ this.section.addMenuItem(this._activeConnectionItem); -+ } -+ if (this._connections.length > 0) { -+ for(let j =3D 0; j < this._connections.length; ++j) { -+ let obj =3D this._connections[j]; -+ if (this._activeConnection && -+ obj.connection =3D=3D this._activeConnection._conne= ction) -+ continue; -+ obj.item =3D this._createConnectionItem(obj); -+ this.section.addMenuItem(obj.item); -+ } -+ } else if (this._autoConnectionName) { -+ this._autoConnectionItem =3D new PopupMenu.PopupMenuItem(th= is._autoConnectionName); -+ this._autoConnectionItem.connect('activate', Lang.bind(this= , function() { -+ let connection =3D this._createAutomaticConnection(); -+ this._client.add_and_activate_connection(connection, th= is.device, null, null); -+ })); -+ this.section.addMenuItem(this._autoConnectionItem); -+ } -+ }, -+ -+ _createConnectionItem: function(obj) { -+ let path =3D obj.connection.path; -+ let item =3D new PopupMenu.PopupMenuItem(obj.name); -+ item.connect('activate', Lang.bind(this, function() { -+ this._client.activate_connection(path, this.device, null, n= ull); -+ })); -+ return item; -+ }, -+ -+ _createActiveConnectionItem: function() { -+ let title; -+ let active =3D this._activeConnection._connection; -+ if (active) { -+ title =3D active._name; -+ } else { -+ /* TRANSLATORS: this is the indication that a connection fo= r another logged in user is active, -+ and we cannot access its settings (including the name) *= / -+ title =3D _("Connected (private)"); -+ } -+ this._activeConnectionItem =3D new PopupMenu.PopupMenuItem(titl= e, { reactive: false }); -+ this._activeConnectionItem.setShowDot(true); -+ }, -+ -+ deviceStateChanged: function(device, newstate, oldstate, reason) { -+ if (newstate =3D=3D oldstate) { -+ log('device emitted state-changed without actually changing= state'); -+ return; -+ } -+ -+ if (oldstate =3D=3D NetworkManager.DeviceState.ACTIVATED) { -+ this.emit('network-lost'); -+ } -+ -+ switch(newstate) { -+ case NetworkManager.DeviceState.NEED_AUTH: -+ // FIXME: make this have a real effect -+ // (currently we rely on a running nm-applet) -+ this.emit('need-auth'); -+ break; -+ case NetworkManager.DeviceState.FAILED: -+ this.emit('activation-failed', reason); -+ break; -+ } -+ -+ this.statusItem.setStatus(this.getStatusLabel()); -+ this.statusItem.setToggleState(this.connected); -+ -+ this._clearSection(); -+ this._createSection(); -+ this.emit('state-changed'); -+ } -+}; -+Signals.addSignalMethods(NMDevice.prototype); -+ -+ -+function NMDeviceWired() { -+ this._init.apply(this, arguments); -+} -+ -+NMDeviceWired.prototype =3D { -+ __proto__: NMDevice.prototype, -+ -+ _init: function(client, device, connections) { -+ this._autoConnectionName =3D _("Auto Ethernet"); -+ this.category =3D NMConnectionCategory.WIRED; -+ -+ NMDevice.prototype._init.call(this, client, device, connections= ); -+ }, -+ -+ connectionValid: function(connection) { -+ if (connection._type !=3D NetworkManager.SETTING_WIRED_SETTING_= NAME) -+ return false; -+ -+ let ethernetSettings =3D connection.get_setting_by_name(Network= Manager.SETTING_WIRED_SETTING_NAME); -+ let fixedMac =3D ethernetSettings.get_mac_address(); -+ if (fixedMac) -+ return macCompare(fixedMac, macToArray(this.device.perm_hw_= address)); -+ return true; -+ }, -+ -+ _createAutomaticConnection: function() { -+ let connection =3D new NetworkManager.Connection(); -+ connection._uuid =3D NetworkManager.utils_uuid_generate(); -+ connection.add_setting(new NetworkManager.SettingWired()); -+ connection.add_setting(new NetworkManager.SettingConnection({ -+ uuid: connection._uuid, -+ id: this._autoConnectionName, -+ type: NetworkManager.SETTING_WIRED_SETTING_NAME, -+ autoconnect: true -+ })); -+ return connection; -+ } -+}; -+ -+function NMDeviceModem() { -+ this._init.apply(this, arguments); -+} -+ -+NMDeviceModem.prototype =3D { -+ __proto__: NMDevice.prototype, -+ -+ _init: function(client, device, connections) { -+ let is_wwan =3D false; -+ -+ this._enabled =3D true; -+ this.mobileDevice =3D null; -+ this._connectionType =3D 'ppp'; -+ -+ this._capabilities =3D device.current_capabilities; -+ if (this._capabilities & NetworkManager.DeviceModemCapabilities= .GSM_UMTS) { -+ is_wwan =3D true; -+ this.mobileDevice =3D new ModemManager.ModemGsm(device.udi)= ; -+ this._connectionType =3D NetworkManager.SETTING_GSM_SETTING= _NAME; -+ } else if (this._capabilities & NetworkManager.DeviceModemCapab= ilities.CDMA_EVDO) { -+ is_wwan =3D true; -+ this.mobileDevice =3D new ModemManager.ModemCdma(device.udi= ); -+ this._connectionType =3D NetworkManager.SETTING_CDMA_SETTIN= G_NAME; -+ } else if (this._capabilities & NetworkManager.DeviceModemCapab= ilities.LTE) { -+ is_wwan =3D true; -+ // FIXME: support signal quality -+ } -+ -+ if (is_wwan) { -+ this.category =3D NMConnectionCategory.WWAN; -+ this._autoConnectionName =3D _("Auto broadband"); -+ } else { -+ this.category =3D NMConnectionCategory.WIRED; -+ this._autoConnectionName =3D _("Auto dial-up"); -+ } -+ -+ if (this.mobileDevice) { -+ this._operatorNameId =3D this.mobileDevice.connect('notify:= :operator-name', Lang.bind(this, function() { -+ if (this._operatorItem) { -+ let name =3D this.mobileDevice.operator_name; -+ if (name) { -+ this._operatorItem.label.text =3D name; -+ this._operatorItem.actor.show(); -+ } else -+ this._operatorItem.actor.hide(); -+ } -+ })); -+ this._signalQualityId =3D this.mobileDevice.connect('notify= ::signal-quality', Lang.bind(this, function() { -+ if (this._operatorItem) { -+ this._operatorItem.setIcon(this._getSignalIcon()); -+ } -+ })); -+ } -+ -+ NMDevice.prototype._init.call(this, client, device, connections= , 1); -+ }, -+ -+ setEnabled: function(enabled) { -+ this._enabled =3D enabled; -+ if (this.category =3D=3D NMConnectionCategory.WWAN) { -+ if (enabled) { -+ // prevent "network unavailable" statuses -+ this.statusItem.setStatus(null); -+ } else -+ this.statusItem.setStatus(this.getStatusLabel()); -+ } -+ -+ NMDevice.prototype.setEnabled.call(this, enabled); -+ }, -+ -+ get connected() { -+ return this._enabled && this.device.state =3D=3D NetworkManager= .DeviceState.CONNECTED; -+ }, -+ -+ destroy: function() { -+ if (this._operatorNameId) { -+ this.mobileDevice.disconnect(this._operatorNameId); -+ this._operatorNameId =3D 0; -+ } -+ if (this._signalQualityId) { -+ this.mobileDevice.disconnect(this._signalQualityId); -+ this._signalQualityId =3D 0; -+ } -+ -+ NMDevice.prototype.destroy.call(this); -+ }, -+ -+ _getSignalIcon: function() { -+ return 'network-cellular-signal-' + signalToIcon(this.mobileDev= ice.signal_quality); -+ }, -+ -+ _createSection: function() { -+ if (this.mobileDevice) { -+ // If operator_name is null, just pass the empty string, as= the item is hidden anyway -+ this._operatorItem =3D new PopupMenu.PopupImageMenuItem(thi= s.mobileDevice.operator_name || '', -+ this.= _getSignalIcon(), -+ { rea= ctive: false }); -+ if (this.mobileDevice.operator_name) -+ this._operatorItem.actor.hide(); -+ this.section.addMenuItem(this._operatorItem); -+ } -+ -+ NMDevice.prototype._createSection.call(this); -+ }, -+ -+ clearSection: function() { -+ this._operatorItem =3D null; -+ -+ NMDevice.prototype._clearSection.call(this); -+ }, -+ -+ connectionValid: function(connection) { -+ return connection._type =3D=3D this._connectionType; -+ }, -+ -+ _createAutomaticConnection: function() { -+ // FIXME: we need to summon the mobile wizard here -+ // or NM will not have the necessary parameters to complete the= connection -+ // pending a DBus method on nm-applet -+ -+ let connection =3D new NetworkManager.Connection; -+ connection._uuid =3D NetworkManager.utils_uuid_generate(); -+ connection.add_setting(new NetworkManager.SettingConnection({ -+ uuid: connection._uuid, -+ id: this._autoConnectionName, -+ type: this._connectionType, -+ autoconnect: false -+ })); -+ return connection; -+ } -+}; -+ -+function NMDeviceBluetooth() { -+ this._init.apply(this, arguments); -+} -+ -+NMDeviceBluetooth.prototype =3D { -+ __proto__: NMDevice.prototype, -+ -+ _init: function(client, device, connections) { -+ this._autoConnectionName =3D this._makeConnectionName(device); -+ device.connect('notify::name', Lang.bind(this, this._updateAuto= ConnectionName)); -+ -+ this.category =3D NMConnectionCategory.WWAN; -+ -+ NMDevice.prototype._init.call(this, client, device, connections= ); -+ }, -+ -+ connectionValid: function(connection) { -+ if (connection._type !=3D NetworkManager.SETTING_BLUETOOTH_SETT= ING_NAME) -+ return false; -+ -+ let bluetoothSettings =3D connection.get_setting_by_name(Networ= kManager.SETTING_BLUETOOTH_SETTING_NAME); -+ let fixedBdaddr =3D bluetoothSettings.get_bdaddr(); -+ if (fixedBdaddr) -+ return macCompare(fixedBdaddr, macToArray(this.device.hw_ad= dress)); -+ -+ return true; -+ }, -+ -+ _createAutomaticConnection: function() { -+ let connection =3D new NetworkManager.Connection; -+ connection._uuid =3D NetworkManager.utils_uuid_generate(); -+ connection.add_setting(new NetworkManager.SettingBluetooth); -+ connection.add_setting(new NetworkManager.SettingConnection({ -+ uuid: connection._uuid, -+ id: this._autoConnectionName, -+ type: NetworkManager.SETTING_BLUETOOTH_SETTING_NAME, -+ autoconnect: false -+ })); -+ return connection; -+ }, -+ -+ _makeConnectionName: function(device) { -+ let name =3D device.name; -+ if (name) -+ return _("Auto %s").format(name); -+ else -+ return _("Auto bluetooth"); -+ }, -+ -+ _updateAutoConnectionName: function() { -+ this._autoConnectionName =3D this._makeConnectioName(this.devic= e); -+ -+ this._clearSection(); -+ this._createSection(); -+ } -+}; -+ -+ -+// Not a real device, but I save a lot code this way -+function NMDeviceVPN() { -+ this._init.apply(this, arguments); -+} -+ -+NMDeviceVPN.prototype =3D { -+ __proto__: NMDevice.prototype, -+ -+ _init: function(client) { -+ // Disable autoconnections -+ this._autoConnectionName =3D null; -+ this.category =3D NMConnectionCategory.VPN; -+ -+ NMDevice.prototype._init.call(this, client, null, [ ]); -+ }, -+ -+ connectionValid: function(connection) { -+ return connection._type =3D=3D NetworkManager.SETTING_VPN_SETTI= NG_NAME; -+ }, -+ -+ get empty() { -+ return this._connections.length =3D=3D 0; -+ }, -+ -+ get connected() { -+ return true; -+ }, -+ -+ _shouldShowConnectionList: function() { -+ return true; -+ }, -+ -+ deactivate: function() { -+ if (this._activeConnection) -+ this._client.deactivate_connection(this._activeConnection); -+ }, -+ -+ getStatusLabel: function() { -+ return null; -+ } -+}; -+ -+function NMDeviceWireless() { -+ this._init.apply(this, arguments); -+} -+ -+NMDeviceWireless.prototype =3D { -+ __proto__: NMDevice.prototype, -+ -+ _init: function(client, device, connections) { -+ this.category =3D NMConnectionCategory.WIRELESS; -+ -+ this._overflowItem =3D null; -+ this._networks =3D [ ]; -+ -+ // XXX: breaking the layers with this, but cannot call -+ // this.connectionValid until I have a device -+ this.device =3D device; -+ -+ let validConnections =3D connections.filter(Lang.bind(this, fun= ction(connection) { -+ return this.connectionValid(connection); -+ })); -+ let accessPoints =3D device.get_access_points() || [ ]; -+ for (let i =3D 0; i < accessPoints.length; i++) { -+ // Access points are grouped by network -+ let ap =3D accessPoints[i]; -+ let pos =3D this._findNetwork(ap); -+ let obj; -+ if (pos !=3D -1) { -+ obj =3D this._networks[pos]; -+ obj.accessPoints.push(ap); -+ } else { -+ obj =3D { ssid: ssid, -+ mode: ap.mode, -+ security: getApSecurityType(ap), -+ connections: [ ], -+ item: null, -+ accessPoints: [ ap ] -+ }; -+ this._networks.push(obj); -+ } -+ -+ // Check if some connection is valid for this AP -+ for (let j =3D 0; j < validConnections.length; j++) { -+ let connection =3D validConnections[j]; -+ if (this._connectionValidForAP(connection, ap) && -+ obj.connections.indexOf(connection) =3D=3D -1) { -+ obj.connections.push(connection); -+ } -+ } -+ } -+ this._apAddedId =3D device.connect('access-point-added', Lang.b= ind(this, this._accessPointAdded)); -+ this._apRemovedId =3D device.connect('access-point-removed', La= ng.bind(this, this._accessPointRemoved)); -+ -+ NMDevice.prototype._init.call(this, client, device, validConnec= tions); -+ }, -+ -+ destroy: function() { -+ if (this._apAddedId) { -+ // see above for this HACK -+ GObject.Object.prototype.disconnect.call(this.device, this.= _apAddedId); -+ this._apAddedId =3D 0; -+ } -+ -+ if (this._apRemovedId) { -+ GObject.Object.prototype.disconnect.call(this.device, this.= _apRemovedId); -+ this._apRemovedId =3D 0; -+ } -+ -+ NMDevice.prototype.destroy.call(this); -+ }, -+ -+ setEnabled: function(enabled) { -+ if (enabled) { -+ this.statusItem.actor.show(); -+ this.section.actor.show(); -+ } else { -+ this.statusItem.actor.hide(); -+ this.section.actor.hide(); -+ } -+ }, -+ -+ activate: function() { -+ if (this._activeConnection) -+ // nothing to do -+ return; -+ -+ // among all visible networks, pick the last recently used conn= ection -+ let best =3D null; -+ let bestApObj =3D null; -+ let bestTime =3D 0; -+ for (let i =3D 0; i < this._networks.length; i++) { -+ let apObj =3D this._networks[i]; -+ for (let j =3D 0; j < apObj.connections.length; j++) { -+ let connection =3D apObj.connections[j]; -+ if (connection._timestamp > bestTime) { -+ best =3D connection; -+ bestTime =3D connection._timestamp; -+ bestApObj =3D apObj; -+ } -+ } -+ } -+ -+ if (best) { -+ for (let i =3D 0; i < bestApObj.accessPoints.length; i++) { -+ let ap =3D bestApObj.accessPoints[i]; -+ if (this._connectionValidForAP(best, ap)) { -+ this._client.activate_connection(best.path, this.de= vice, ap.dbus_path, null); -+ break; -+ } -+ } -+ return; -+ } -+ -+ // XXX: what else to do? -+ // for now, just pick a random network -+ // (this function is called in a corner case anyway, that is, o= nly when -+ // the user toggles the switch and has more than one wireless d= evice) -+ if (this._networks.length > 0) { -+ let connection =3D this._createAutomaticConnection(this._ne= tworks[0]); -+ let accessPoints =3D sortAccessPoints(this._networks[0].acc= essPoints); -+ this._client.add_and_activate_connection(connection, this.d= evice, accessPoints[0].dbus_path, null); -+ } -+ }, -+ -+ _networkCompare: function(network, accessPoint) { -+ if (!ssidCompare(network.ssid, accessPoint.get_ssid())) -+ return false; -+ if (network.mode !=3D accessPoint.mode) -+ return false; -+ if (network.security !=3D getApSecurityType(accessPoint)) -+ return false; -+ -+ return true; -+ }, -+ -+ _findNetwork: function(accessPoint) { -+ for (let i =3D 0; i < this._networks.length; i++) { -+ if (this._networkCompare(this._networks[i], accessPoint)) -+ return i; -+ } -+ return -1; -+ }, -+ -+ _accessPointAdded: function(device, accessPoint) { -+ let pos =3D this._findNetwork(accessPoint); -+ let apObj; -+ if (pos !=3D -1) { -+ apObj =3D this._networks[pos]; -+ if (apObj.accessPoints.indexOf(accessPoint) !=3D -1) { -+ log('Access point was already seen, not adding again'); -+ return; -+ } -+ -+ apObj.accessPoints.push(accessPoint); -+ } else { -+ apObj =3D { ssid: ssid, -+ mode: accessPoint.mode, -+ security: getApSecurityType(accessPoint), -+ connections: [ ], -+ item: null, -+ accessPoints: [ accessPoint ] -+ }; -+ this._networks.push(apObj); -+ } -+ -+ // check if this enables new connections for this group -+ for (let i =3D 0; i < this._connections.length; i++) { -+ let connection =3D this._connections[i].connection; -+ if (this._connectionValidForAP(connection, accessPoint) && -+ apObj.connections.indexOf(connection) =3D=3D -1) { -+ apObj.connections.push(connection); -+ } -+ } -+ -+ // update everything -+ this._clearSection(); -+ this._createSection(); -+ }, -+ -+ _accessPointRemoved: function(device, accessPoint) { -+ let pos =3D this._findNetwork(accessPoint); -+ -+ if (pos =3D=3D -1) { -+ log('Removing an access point that was never added'); -+ return; -+ } -+ -+ let apObj =3D this._networks[pos]; -+ let i =3D apObj.accessPoints.indexOf(accessPoint); -+ -+ if (i =3D=3D -1) { -+ log('Removing an access point that was never added'); -+ return; -+ } -+ -+ apObj.accessPoints.splice(i, 1); -+ -+ if (apObj.accessPoints.length =3D=3D 0) { -+ if (apObj.item) -+ apObj.item.destroy(); -+ this._networks.splice(pos, 1); -+ } else if (apObj.item) -+ apObj.item.updateAccessPoints(apObj.accessPoints); -+ }, -+ -+ _createAPItem: function(connection, accessPointObj, useConnectionNa= me) { -+ let item =3D new NMNetworkMenuItem(accessPointObj.accessPoints,= useConnectionName ? connection._name : undefined); -+ item._connection =3D connection; -+ item.connect('activate', Lang.bind(this, function() { -+ let accessPoints =3D sortAccessPoints(accessPointObj.access= Points); -+ for (let i =3D 0; i < accessPoints.length; i++) { -+ if (this._connectionValidForAP(connection, accessPoints= [i])) { -+ this._client.activate_connection(connection.path, t= his.device, accessPoints[i].dbus_path, null); -+ break; -+ } -+ } -+ })); -+ return item; -+ }, -+ -+ connectionValid: function(connection) { -+ if (connection._type !=3D NetworkManager.SETTING_WIRELESS_SETTI= NG_NAME) -+ return false; -+ -+ let wirelessSettings =3D connection.get_setting_by_name(Network= Manager.SETTING_WIRELESS_SETTING_NAME); -+ let wirelessSecuritySettings =3D connection.get_setting_by_name= (NetworkManager.SETTING_WIRELESS_SECURITY_SETTING_NAME); -+ -+ let fixedMac =3D wirelessSettings.get_mac_address(); -+ if (fixedMac && !macCompare(fixedMac, macToArray(this.device.pe= rm_hw_address))) -+ return false; -+ -+ if (wirelessSecuritySettings && -+ wirelessSecuritySettings.key_mgmt !=3D 'none' && -+ wirelessSecuritySettings.key_mgmt !=3D 'ieee8021x') { -+ let capabilities =3D this.device.wireless_capabilities; -+ if (!(capabilities & NetworkManager.DeviceWifiCapabilities.= WPA) || -+ !(capabilities & NetworkManager.DeviceWifiCapabilities.= CIPHER_TKIP)) -+ return false; -+ if (wirelessSecuritySettings.get_num_protos() =3D=3D 1 && -+ wirelessSecuritySettings.get_proto(0) =3D=3D 'rsn' && -+ !(capabilities & NetworkManager.DeviceWifiCapabilities.= RSN)) -+ return false; -+ if (wirelessSecuritySettings.get_num_pairwise() =3D=3D 1 && -+ wirelessSecuritySettings.get_pairwise(0) =3D=3D 'ccmp' = && -+ !(capabilities & NetworkManager.DeviceWifiCapabilities.= CIPHER_CCMP)) -+ return false; -+ if (wirelessSecuritySettings.get_num_groups() =3D=3D 1 && -+ wirelessSecuritySettings.get_group(0) =3D=3D 'ccmp' && -+ !(capabilities & NetworkManager.DeviceWifiCapabilities.= CIPHER_CCMP)) -+ return false; -+ } -+ return true; -+ }, -+ -+ _clearSection: function() { -+ NMDevice.prototype._clearSection.call(this); -+ -+ for (let i =3D 0; i < this._networks.length; i++) -+ this._networks[i].item =3D null; -+ this._overflowItem =3D null; -+ }, -+ -+ removeConnection: function(connection) { -+ if (!connection._uuid) -+ return; -+ let pos =3D this._findConnection(connection._uuid); -+ if (pos =3D=3D -1) { -+ // removing connection that was never added -+ return; -+ } -+ -+ let obj =3D this._connections[pos]; -+ this._connections.splice(pos, 1); -+ -+ let anyauto =3D false, forceupdate =3D false; -+ for (let i =3D 0; i < this._networks.length; i++) { -+ let apObj =3D this._networks[i]; -+ let connections =3D apObj.connections; -+ for (let k =3D 0; k < connections.length; k++) { -+ if (connections[k]._uuid =3D=3D connection._uuid) { -+ // remove the connection from the access point grou= p -+ connections.splice(k); -+ anyauto =3D connections.length =3D=3D 0; -+ if (apObj.item) { -+ if (apObj.item instanceof PopupMenu.PopupSubMen= uMenuItem) { -+ let items =3D apObj.item.menu.getMenuItems(= ); -+ if (items.length =3D=3D 2) { -+ // we need to update the connection lis= t to convert this to a normal item -+ forceupdate =3D true; -+ } else { -+ for (let j =3D 0; j < items.length; j++= ) { -+ if (items[j]._connection._uuid =3D=3D= connection._uuid) { -+ items[j].destroy(); -+ break; -+ } -+ } -+ } -+ } else { -+ apObj.item.destroy(); -+ apObj.item =3D null; -+ } -+ } -+ break; -+ } -+ } -+ } -+ -+ if (forceupdate || anyauto) { -+ this._clearSection(); -+ this._createSection(); -+ } -+ }, -+ -+ addConnection: function(connection) { -+ // record the connection -+ let obj =3D { -+ connection: connection, -+ name: connection._name, -+ uuid: connection._uuid, -+ }; -+ this._connections.push(obj); -+ -+ // find an appropriate access point -+ let any =3D false, forceupdate =3D false; -+ for (let i =3D 0; i < this._networks.length; i++) { -+ let apObj =3D this._networks[i]; -+ -+ // Check if connection is valid for any of these access poi= nts -+ let any =3D false; -+ for (let k =3D 0; k < apObj.accessPoints.length; k++) { -+ let ap =3D apObj.accessPoints[k]; -+ if (this._connectionValidForAP(connection, ap)) { -+ apObj.connections.push(connection); -+ any =3D true; -+ break; -+ } -+ } -+ -+ if (any && this._shouldShowConnectionList() && !skipCreateM= enu) {=20 -+ // we need to show this connection -+ if (apObj.item && apObj.item.menu) { -+ // We're already showing the submenu for this acces= s point -+ apObj.item.menu.addMenuItem(this._createAPItem(conn= ection, apObj, true)); -+ } else { -+ if (apObj.item) -+ apObj.item.destroy(); -+ if (apObj.connections.length =3D=3D 1) { -+ apObj.item =3D this._createAPItem(connection, a= pObj, false); -+ this.section.addMenuItem(apObj.item); -+ } else { -+ apObj.item =3D null; -+ // we need to force an update to create the sub= menu -+ forceupdate =3D true; -+ } -+ } -+ } -+ } -+ -+ if (forceupdate) { -+ this._clearSection(); -+ this._createSection(); -+ } -+ }, -+ -+ _connectionValidForAP: function(connection, ap) { -+ // copied and adapted from nm-applet -+ let wirelessSettings =3D connection.get_setting_by_name(Network= Manager.SETTING_WIRELESS_SETTING_NAME); -+ if (!ssidCompare(wirelessSettings.get_ssid(), ap.get_ssid())) -+ return false; -+ -+ let wirelessSecuritySettings =3D connection.get_setting_by_name= (NetworkManager.SETTING_WIRELESS_SECURITY_SETTING_NAME); -+ -+ let fixedBssid =3D wirelessSettings.get_bssid(); -+ if (fixedBssid && !macCompare(fixedBssid, macToArray(ap.hw_addr= ess))) -+ return false; -+ -+ let fixedBand =3D wirelessSettings.band; -+ if (fixedBand) { -+ let freq =3D ap.frequency; -+ if (fixedBand =3D=3D 'a' && (freq < 4915 || freq > 5825)) -+ return false; -+ if (fixedBand =3D=3D 'bg' && (freq < 2412 || freq > 2484)) -+ return false; -+ } -+ -+ let fixedChannel =3D wirelessSettings.channel; -+ if (fixedChannel && fixedChannel !=3D NetworkManager.utils_wifi= _freq_to_channel(ap.frequency)) -+ return false; -+ -+ if (!wirelessSecuritySettings) -+ return true; -+ -+ return wirelessSettings.ap_security_compatible(wirelessSecurity= Settings, ap.flags, ap.wpa_flags, ap.rsn_flags, ap.mode); -+ }, -+ -+ _createActiveConnectionItem: function() { -+ let activeAp =3D this.device.active_access_point; -+ let icon, title; -+ if (this._activeConnection._connection) { -+ let connection =3D this._activeConnection._connection; -+ if (activeAp) -+ this._activeConnectionItem =3D new NMNetworkMenuItem([ = activeAp ], undefined, -+ = { reactive: false }); -+ else -+ this._activeConnectionItem =3D new PopupMenu.PopupImage= MenuItem(connection._name, -+ = 'network-wireless-connected', -+ = { reactive: false }); -+ } else { -+ // We cannot read the connection (due to ACL, or API incomp= atibility), but we still show signal if we have it -+ let menuItem; -+ if (activeAp) -+ this._activeConnectionItem =3D new NMNetworkMenuItem([ = activeAp ], undefined, -+ = { reactive: false }); -+ else -+ this._activeConnectionItem =3D new PopupMenu.PopupImage= MenuItem(_("Connected (private)"), -+ = 'network-wireless-connected', -+ = { reactive: false }); -+ } -+ this._activeConnectionItem.setShowDot(true); -+ }, -+ -+ _createAutomaticConnection: function(apObj) { -+ let name; -+ let ssid =3D NetworkManager.utils_ssid_to_utf8(apObj.ssid); -+ if (ssid) { -+ /* TRANSLATORS: this the automatic wireless connection name= (including the network name) */ -+ name =3D _("Auto %s").format(ssid); -+ } else -+ name =3D _("Auto wireless"); -+ -+ let connection =3D new NetworkManager.Connection(); -+ connection.add_setting(new NetworkManager.SettingWireless()); -+ connection.add_setting(new NetworkManager.SettingConnection({ -+ id: name, -+ autoconnect: true, // NetworkManager will know to ignore th= is if appropriate -+ uuid: NetworkManager.utils_uuid_generate(), -+ type: NetworkManager.SETTING_WIRELESS_SETTING_NAME -+ })); -+ return connection; -+ }, -+ -+ _createSection: function() { -+ if (!this._shouldShowConnectionList()) -+ return; -+ -+ if(this._activeConnection) { -+ this._createActiveConnectionItem(); -+ this.section.addMenuItem(this._activeConnectionItem); -+ } -+ -+ let activeAp =3D this.device.active_access_point; -+ let activeApSsid =3D activeAp ? activeAp.get_ssid() : null; -+ -+ // we want five access points in the menu, including the active= one -+ let numItems =3D this._activeConnection ? 4 : 5; -+ -+ for(let j =3D 0; j < this._networks.length; j++) { -+ let apObj =3D this._networks[j]; -+ if(activeAp && ssidCompare(apObj.ssid, activeApSsid)) -+ continue; -+ -+ let menuItem; -+ if(apObj.connections.length > 0) { -+ if (apObj.connections.length =3D=3D 1) -+ apObj.item =3D this._createAPItem(apObj.connections= [0], apObj, false); -+ else { -+ let title =3D NetworkManager.utils_ssid_to_utf8(apO= bj.ssid) || _(""); -+ apObj.item =3D new PopupMenu.PopupSubMenuMenuItem(t= itle); -+ apObj.item._apObj =3D apObj; -+ for (let i =3D 0; i < apObj.connections.length; i++= ) -+ apObj.item.menu.addMenuItem(this._createAPItem(= apObj.connections[i], apObj, true)); -+ } -+ } else { -+ apObj.item =3D new NMNetworkMenuItem(apObj.accessPoints= ); -+ apObj.item._apObj =3D apObj; -+ apObj.item.connect('activate', Lang.bind(this, function= () { -+ let connection =3D this._createAutomaticConnection(= apObj); -+ let accessPoints =3D sortAccessPoints(apObj.accessP= oints); -+ this._client.add_and_activate_connection(connection= , this.device, accessPoints[0].dbus_path, null) -+ })); -+ } -+ -+ if (j < numItems) -+ this.section.addMenuItem(apObj.item); -+ else { -+ if (!this._overflowItem) { -+ this._overflowItem =3D new PopupMenu.PopupSubMenuMe= nuItem(_("More...")); -+ this.section.addMenuItem(this._overflowItem); -+ } -+ this._overflowItem.menu.addMenuItem(apObj.item); -+ } -+ } -+ }, -+}; -+ -+function NMApplet() { -+ this._init.apply(this, arguments); -+} -+NMApplet.prototype =3D { -+ __proto__: PanelMenu.SystemStatusButton.prototype, -+ -+ _init: function() { -+ PanelMenu.SystemStatusButton.prototype._init.call(this, 'networ= k-error'); -+ -+ this._client =3D NMClient.Client.new(); -+ -+ this._statusSection =3D new PopupMenu.PopupMenuSection(); -+ this._statusItem =3D new PopupMenu.PopupMenuItem('', { style_cl= ass: 'popup-inactive-menu-item', reactive: false }); -+ this._statusSection.addMenuItem(this._statusItem); -+ this._statusSection.addAction(_("Enable networking"), Lang.bind= (this, function() { -+ this._client.networking_enabled =3D true; -+ })); -+ this._statusSection.addMenuItem(new PopupMenu.PopupSeparatorMen= uItem()); -+ this._statusSection.actor.hide(); -+ this.menu.addMenuItem(this._statusSection); -+ -+ this._devices =3D { }; -+ -+ this._devices.wired =3D { -+ section: new PopupMenu.PopupMenuSection(), -+ devices: [ ], -+ item: new NMWiredSectionTitleMenuItem(_("Wired")) -+ }; -+ -+ this._devices.wired.section.addMenuItem(this._devices.wired.ite= m); -+ this._devices.wired.section.addMenuItem(new PopupMenu.PopupSepa= ratorMenuItem()); -+ this._devices.wired.section.actor.hide(); -+ this.menu.addMenuItem(this._devices.wired.section); -+ -+ this._devices.wireless =3D { -+ section: new PopupMenu.PopupMenuSection(), -+ devices: [ ], -+ item: this._makeToggleItem('wireless', _("Wireless")) -+ }; -+ this._devices.wireless.section.addMenuItem(this._devices.wirele= ss.item); -+ this._devices.wireless.section.addMenuItem(new PopupMenu.PopupS= eparatorMenuItem()); -+ this._devices.wireless.section.actor.hide(); -+ this.menu.addMenuItem(this._devices.wireless.section); -+ -+ this._devices.wwan =3D { -+ section: new PopupMenu.PopupMenuSection(), -+ devices: [ ], -+ item: this._makeToggleItem('wwan', _("Mobile broadband")) -+ }; -+ this._devices.wwan.section.addMenuItem(this._devices.wwan.item)= ; -+ this._devices.wwan.section.addMenuItem(new PopupMenu.PopupSepar= atorMenuItem()); -+ this._devices.wwan.section.actor.hide(); -+ this.menu.addMenuItem(this._devices.wwan.section); -+ -+ this._devices.vpn =3D { -+ section: new PopupMenu.PopupMenuSection(), -+ device: new NMDeviceVPN(this._client), -+ item: new NMWiredSectionTitleMenuItem(_("VPN Connections")) -+ }; -+ this._devices.vpn.item.updateForDevice(this._devices.vpn.device= ); -+ this._devices.vpn.section.addMenuItem(this._devices.vpn.item); -+ this._devices.vpn.section.addMenuItem(this._devices.vpn.device.= section); -+ this._devices.vpn.section.addMenuItem(new PopupMenu.PopupSepara= torMenuItem()); -+ this._devices.vpn.section.actor.hide(); -+ this.menu.addMenuItem(this._devices.vpn.section); -+ -+ this.menu.addAction(_("Network Settings"), function() { -+ Util.spawnDesktop('gnome-network-panel'); -+ }); -+ -+ this._activeConnections =3D [ ]; -+ this._connections =3D [ ]; -+ -+ this._mainConnection =3D null; -+ this._activeAccessPointUpdateId =3D 0; -+ this._activeAccessPoint =3D null; -+ this._mobileUpdateId =3D 0; -+ this._mobileUpdateDevice =3D null; -+ -+ // Device types -+ this._dtypes =3D { }; -+ this._dtypes[NetworkManager.DeviceType.ETHERNET] =3D NMDeviceWi= red; -+ this._dtypes[NetworkManager.DeviceType.WIFI] =3D NMDeviceWirele= ss; -+ this._dtypes[NetworkManager.DeviceType.MODEM] =3D NMDeviceModem= ; -+ this._dtypes[NetworkManager.DeviceType.BT] =3D NMDeviceBluetoot= h; -+ // TODO: WiMax support -+ -+ // Connection types -+ this._ctypes =3D { }; -+ this._ctypes[NetworkManager.SETTING_WIRELESS_SETTING_NAME] =3D = NMConnectionCategory.WIRELESS; -+ this._ctypes[NetworkManager.SETTING_WIRED_SETTING_NAME] =3D NMC= onnectionCategory.WIRED; -+ this._ctypes[NetworkManager.SETTING_PPPOE_SETTING_NAME] =3D NMC= onnectionCategory.WIRED; -+ this._ctypes[NetworkManager.SETTING_PPP_SETTING_NAME] =3D NMCon= nectionCategory.WIRED; -+ this._ctypes[NetworkManager.SETTING_BLUETOOTH_SETTING_NAME] =3D= NMConnectionCategory.WWAN; -+ this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] =3D NMCo= nnectionCategory.WWAN; -+ this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] =3D NMCon= nectionCategory.WWAN; -+ this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] =3D NMCon= nectionCategory.VPN; -+ -+ this._settings =3D NMClient.RemoteSettings.new(null); -+ this._connectionsReadId =3D this._settings.connect('connections= -read', Lang.bind(this, function() { -+ this._readConnections(); -+ this._readDevices(); -+ this._syncNMState(); -+ -+ // Connect to signals late so that early signals don't find= in inconsistent state -+ // and connect only once (this signal handler can be called= again if NetworkManager goes up and down) -+ if (!this._inited) { -+ this._inited =3D true; -+ this._client.connect('notify::manager-running', Lang.bi= nd(this, this._syncNMState)); -+ this._client.connect('notify::networking-enabled', Lang= .bind(this, this._syncNMState)); -+ this._client.connect('notify::state', Lang.bind(this, t= his._syncNMState)); -+ this._client.connect('notify::active-connections', Lang= .bind(this, this._updateIcon)); -+ this._client.connect('device-added', Lang.bind(this, th= is._deviceAdded)); -+ this._client.connect('device-removed', Lang.bind(this, = this._deviceRemoved)); -+ this._settings.connect('new-connection', Lang.bind(this= , this._newConnection)); -+ } -+ })); -+ }, -+ -+ _ensureSource: function() { -+ if (!this._source) { -+ this._source =3D new NMMessageTraySource(); -+ this._source._destroyId =3D this._source.connect('destroy',= Lang.bind(this, function() { -+ this._source._destroyId =3D 0; -+ this._source =3D null; -+ })); -+ Main.messageTray.add(this._source); -+ } -+ }, -+ -+ _makeToggleItem: function(type, title) { -+ let item =3D new NMWirelessSectionTitleMenuItem(this._client, t= ype, title); -+ item.connect('enabled-changed', Lang.bind(this, function(item, = enabled) { -+ let devices =3D this._devices[type].devices; -+ devices.forEach(function(dev) { -+ dev.setEnabled(enabled); -+ }); -+ this._syncSectionTitle(type); -+ })); -+ return item; -+ }, -+ -+ _syncSectionTitle: function(category) { -+ let devices =3D this._devices[category].devices; -+ let managedDevices =3D devices.filter(function(dev) { -+ return dev.device.state !=3D NetworkManager.DeviceState.UNM= ANAGED; -+ }); -+ let item =3D this._devices[category].item; -+ let section =3D this._devices[category].section; -+ if (managedDevices.length =3D=3D 0) -+ section.actor.hide(); -+ else { -+ section.actor.show(); -+ if (managedDevices.length =3D=3D 1) { -+ let dev =3D managedDevices[0]; -+ dev.statusItem.actor.hide(); -+ item.updateForDevice(dev); -+ } else { -+ managedDevices.forEach(function(dev) { -+ dev.statusItem.actor.show(); -+ }); -+ } -+ } -+ }, -+ -+ _readDevices: function() { -+ let devices =3D this._client.get_devices() || [ ]; -+ for (let i =3D 0; i < devices.length; ++i) { -+ this._deviceAdded(this._client, devices[i]); -+ } -+ }, -+ -+ _deviceAdded: function(client, device) { -+ if (device._delegate) { -+ // already seen, not adding again -+ return; -+ } -+ let wrapperClass =3D this._dtypes[device.get_device_type()]; -+ if (wrapperClass) { -+ device._description =3D getDeviceDescription(device); -+ -+ let wrapper =3D new wrapperClass(this._client, device, this= ._connections); -+ // FIXME: these notifications are duplicate with those expo= sed by nm-applet -+ // uncomment this code in 3.2, when we'll conflict with and= kill nm-applet -+ /* wrapper._networkLostId =3D wrapper.connect('network-lost= ', Lang.bind(this, function(emitter) { -+ this._ensureSource(); -+ let icon =3D new St.Icon({ icon_name: 'network-offline'= , -+ icon_type: St.IconType.SYMBOLI= C, -+ icon_size: this._source.ICON_S= IZE -+ }); -+ let notification =3D new MessageTray.Notification(this.= _source, -+ _("Conn= ectivity lost"), -+ _("You'= re no longer connected to the network"), -+ { icon:= icon }); -+ this._source.notify(notification); -+ })); -+ wrapper._activationFailedId =3D wrapper.connect('activation= -failed', Lang.bind(this, function(wrapper, reason) { -+ this._ensureSource(); -+ let icon =3D new St.Icon({ icon_name: 'network-error', -+ icon_type: St.IconType.SYMBOLI= C, -+ icon_size: this._source.ICON_S= IZE, -+ }); -+ let banner; -+ // XXX: nm-applet has no special text depending on reas= on -+ // but I'm not sure of this generic message -+ let notification =3D new MessageTray.Notification(this.= _source, -+ _("Conn= ection failed"), -+ _("Acti= vation of network connection failed"), -+ { icon:= icon }); -+ this._source.notify(notification); -+ })); */ -+ wrapper._stateChangedId =3D wrapper.connect('state-changed'= , Lang.bind(this, function(dev) { -+ this._syncSectionTitle(dev.category); -+ })); -+ wrapper._destroyId =3D wrapper.connect('destroy', function(= wrapper) { -+ //wrapper.disconnect(wrapper._networkLostId); -+ //wrapper.disconnect(wrapper._activationFailedId); -+ wrapper.disconnect(wrapper._stateChangedId); -+ });=20 -+ let section =3D this._devices[wrapper.category].section; -+ let devices =3D this._devices[wrapper.category].devices; -+ -+ section.addMenuItem(wrapper.section, 1); -+ section.addMenuItem(wrapper.statusItem, 1); -+ devices.push(wrapper); -+ -+ this._syncSectionTitle(wrapper.category); -+ } else -+ log('Invalid network device type, is ' + device.get_device_= type()); -+ }, -+ -+ _deviceRemoved: function(client, device) { -+ if (!device._delegate) { -+ log('Removing a network device that was not added'); -+ return; -+ } -+ -+ let wrapper =3D device._delegate; -+ wrapper.destroy(); -+ -+ let devices =3D this._devices[wrapper.category].devices; -+ let pos =3D devices.indexOf(wrapper); -+ devices.splice(pos, 1); -+ -+ this._syncSectionTitle(wrapper.category) -+ }, -+ -+ _syncActiveConnections: function() { -+ let closedConnections =3D [ ]; -+ let newActiveConnections =3D this._client.get_active_connection= s() || [ ]; -+ for (let i =3D 0; i < this._activeConnections.length; i++) { -+ let a =3D this._activeConnections[i]; -+ if (newActiveConnections.indexOf(a) =3D=3D -1) // connectio= n is removed -+ closedConnections.push(a); -+ } -+ -+ for (let i =3D 0; i < closedConnections.length; i++) { -+ let active =3D closedConnections[i]; -+ if (active._primaryDevice) -+ active._primaryDevice.setActiveConnection(null); -+ if (active._notifyStateId) -+ active.disconnect(active._notifyStateId); -+ if (active._inited) { -+ active.disconnect(active._notifyDefaultId); -+ active.disconnect(active._notifyDefault6Id); -+ active._inited =3D false; -+ } -+ } -+ -+ this._activeConnections =3D newActiveConnections; -+ this._mainConnection =3D null; -+ let activating =3D null; -+ let default_ip4 =3D null; -+ let default_ip6 =3D null; -+ for (let i =3D 0; i < this._activeConnections.length; i++) { -+ let a =3D this._activeConnections[i]; -+ -+ if (!a._inited) { -+ a._notifyDefaultId =3D a.connect('notify::default', Lan= g.bind(this, this._updateIcon)); -+ a._notifyDefault6Id =3D a.connect('notify::default6', L= ang.bind(this, this._updateIcon)); -+ if (a.state =3D=3D NetworkManager.ActiveConnectionState= .ACTIVATING) // prepare to notify to the user -+ a._notifyStateId =3D a.connect('notify::state', Lan= g.bind(this, this._notifyActiveConnection)); -+ else { -+ // notify as soon as possible -+ Mainloop.idle_add(Lang.bind(this, function() { -+ this._notifyActiveConnection(a); -+ })); -+ } -+ -+ a._inited =3D true; -+ } -+ -+ if (!a._connection) { -+ a._connection =3D this._settings.get_connection_by_path= (a.connection); -+ -+ if (a._connection) { -+ a._type =3D a._connection._type; -+ a._section =3D this._ctypes[a._type]; -+ } else { -+ a._connection =3D null; -+ a._type =3D null; -+ a._section =3D null; -+ log('Cannot find connection for active (or connecti= on cannot be read)'); -+ } -+ } -+ -+ if (a['default']) -+ default_ip4 =3D a; -+ if (a.default6) -+ default_ip6 =3D a; -+ -+ if (a.state =3D=3D NetworkManager.ActiveConnectionState.ACT= IVATING) { -+ activating =3D a; -+ -+ // don't set activating connections to devices, NMDevic= e:state-changed -+ // should take care of rebuilding the menu -+ continue; -+ } -+ -+ if (!a._primaryDevice) { -+ if (a._type !=3D NetworkManager.SETTING_VPN_SETTING_NAM= E) { -+ // find a good device to be considered primary -+ a._primaryDevice =3D null; -+ let devices =3D a.get_devices(); -+ for (let j =3D 0; j < devices.length; j++) { -+ let d =3D devices[j]; -+ if (d._delegate) { -+ a._primaryDevice =3D d._delegate; -+ break; -+ } -+ } -+ } else -+ a._primaryDevice =3D this._vpnDevice; -+ -+ if (a._primaryDevice) -+ a._primaryDevice.setActiveConnection(a); -+ } -+ } -+ -+ this._mainConnection =3D activating || default_ip4 || default_i= p6 || this._activeConnections[0] || null; -+ }, -+ -+ _notifyActiveConnection: function(active) { -+ // FIXME: duplicate notifications when nm-applet is running -+ // This code will come back when nm-applet is killed -+ this._syncNMState(); -+ return; -+ -+ if (active.state =3D=3D NetworkManager.ActiveConnectionState.AC= TIVATED) { -+ -+ // notify only connections that are visible -+ if (active._connection) { -+ this._ensureSource(); -+ -+ let icon; -+ let banner; -+ switch (active._section) { -+ case NMConnectionCategory.WWAN: -+ icon =3D 'network-cellular-signal-excellent'; -+ banner =3D _("You're now connected to mobile broadb= and connection '%s'").format(active._connection._name); -+ break; -+ case NMConnectionCategory.WIRELESS: -+ icon =3D 'network-wireless-signal-excellent'; -+ banner =3D _("You're now connected to wireless netw= ork '%s'").format(active._connection._name); -+ break; -+ case NMConnectionCategory.WIRED: -+ icon =3D 'network-wired'; -+ banner =3D _("You're now connected to wired network= '%s'").format(active._connection._name); -+ break; -+ case NMConnectionCategory.VPN: -+ icon =3D 'network-vpn'; -+ banner =3D _("You're now connected to VPN network '= %s'").format(active._connection._name); -+ break; -+ default: -+ // a fallback for a generic 'connected' icon -+ icon =3D 'network-transmit-receive'; -+ banner =3D _("You're now connected to '%s'").format= (active._connection._name); -+ } -+ -+ let iconActor =3D new St.Icon({ icon_name: icon, -+ icon_type: St.IconType.SY= MBOLIC, -+ icon_size: this._source.I= CON_SIZE -+ }); -+ let notification =3D new MessageTray.Notification(this.= _source, -+ _("Conn= ection estabilished"), -+ banner, -+ { icon:= iconActor }); -+ this._source.notify(notification); -+ } -+ -+ if (active._stateChangeId) { -+ active.disconnect(active._stateChangeId); -+ active._stateChangeId =3D 0; -+ } -+ } -+ -+ this._syncNMState(); -+ }, -+ -+ _readConnections: function() { -+ let connections =3D this._settings.list_connections(); -+ for (let i =3D 0; i < connections.length; i++) { -+ let connection =3D connections[i]; -+ if (connection._uuid) { -+ // connection was already seen (for example because Net= workManager was restarted) -+ continue; -+ } -+ connection._removedId =3D connection.connect('removed', Lan= g.bind(this, this._connectionRemoved)); -+ connection._updatedId =3D connection.connect('updated', Lan= g.bind(this, this._updateConnection)); -+ -+ this._updateConnection(connection); -+ this._connections.push(connection); -+ } -+ }, -+ -+ _newConnection: function(settings, connection) { -+ if (connection._uuid) { -+ // connection was already seen -+ return; -+ } -+ -+ connection._removedId =3D connection.connect('removed', Lang.bi= nd(this, this._connectionRemoved)); -+ connection._updatedId =3D connection.connect('updated', Lang.bi= nd(this, this._updateConnection)); -+ -+ this._updateConnection(connection); -+ this._connections.push(connection); -+ -+ this._updateIcon(); -+ }, -+ -+ _connectionRemoved: function(connection) { -+ let pos =3D this._connections.indexOf(connection); -+ if (pos !=3D -1) -+ this._connections.splice(connection); -+ -+ let section =3D connection._section; -+ if (section =3D=3D NMConnectionCategory.VPN) { -+ this._devices.vpn.device.removeConnection(connection); -+ if (this._devices.vpn.device.empty) -+ this._devices.vpn.section.actor.hide(); -+ } else { -+ let devices =3D this._devices[section].devices; -+ for (let i =3D 0; i < devices.length; i++) -+ devices[i].removeConnection(connection); -+ } -+ -+ connection._uuid =3D null; -+ connection.disconnect(connection._removedId); -+ connection.disconnect(connection._updatedId); -+ }, -+ -+ _updateConnection: function(connection) { -+ let connectionSettings =3D connection.get_setting_by_name(Netwo= rkManager.SETTING_CONNECTION_SETTING_NAME); -+ connection._type =3D connectionSettings.type; -+ connection._section =3D this._ctypes[connection._type]; -+ connection._name =3D connectionSettings.id; -+ connection._uuid =3D connectionSettings.uuid; -+ connection._timestamp =3D connectionSettings.timestamp; -+ -+ let section =3D connection._section; -+ if (section =3D=3D NMConnectionCategory.VPN) { -+ this._devices.vpn.device.checkConnection(connection); -+ this._devices.vpn.section.actor.show(); -+ connection._everAdded =3D true; -+ } else { -+ let devices =3D this._devices[section].devices; -+ for (let i =3D 0; i < devices.length; i++) { -+ devices[i].checkConnection(connection); -+ } -+ } -+ }, -+ -+ _hideDevices: function() { -+ this._devicesHidden =3D true; -+ -+ for (let category in this._devices) -+ this._devices[category].section.actor.hide(); -+ }, -+ -+ _showNormal: function() { -+ if (!this._devicesHidden) // nothing to do -+ return; -+ this._devicesHidden =3D false; -+ -+ this._statusSection.actor.hide(); -+ -+ this._syncSectionTitle('wired'); -+ this._syncSectionTitle('wireless'); -+ this._syncSectionTitle('wwan'); -+ -+ if (!this._devices.vpn.device.empty) -+ this._devices.vpn.section.actor.show(); -+ }, -+ -+ _syncNMState: function() { -+ if (!this._client.manager_running) { -+ log('NetworkManager is not running, hiding...'); -+ this.menu.close(); -+ this.actor.hide(); -+ return; -+ } else -+ this.actor.show(); -+ -+ if (!this._client.networking_enabled) { -+ this.setIcon('network-offline'); -+ this._hideDevices(); -+ this._statusItem.label.text =3D _("Networking is disabled")= ; -+ this._statusSection.actor.show(); -+ return; -+ } -+ -+ this._showNormal(); -+ this._updateIcon(); -+ }, -+ -+ _updateIcon: function() { -+ this._syncActiveConnections(); -+ let mc =3D this._mainConnection; -+ let hasApIcon =3D false; -+ let hasMobileIcon =3D false; -+ -+ if (!mc) { -+ this.setIcon('network-offline'); -+ } else if (mc.state =3D=3D NetworkManager.ActiveConnectionState= .ACTIVATING) { -+ switch (mc._section) { -+ case NMConnectionCategory.WWAN: -+ this.setIcon('network-cellular-acquiring'); -+ break; -+ case NMConnectionCategory.WIRELESS: -+ this.setIcon('network-wireless-acquiring'); -+ break; -+ case NMConnectionCategory.WIRED: -+ this.setIcon('network-wired-acquiring'); -+ break; -+ case NMConnectionCategory.VPN: -+ // XXX: there is no network-vpn-acquiring -+ this.setIcon('network-vpn'); -+ break; -+ default: -+ this.setIcon('network-error'); -+ log('Invalid active connection type ' + mc._section); -+ } -+ } else { -+ let dev; -+ switch (mc._section) { -+ case NMConnectionCategory.WIRELESS: -+ dev =3D mc._primaryDevice; -+ if (dev) { -+ let ap =3D dev.device.active_access_point; -+ let mode =3D dev.device.mode; -+ if (!ap) { -+ if (mode !=3D NetworkManager['80211Mode'].ADHOC= ) { -+ log('An active wireless connection, in infr= astructure mode, involves no access point?'); -+ break; -+ } -+ // XXX: there is no network-wireless-connected -+ this.setIcon('network-wireless-signal-excellent= '); -+ } else { -+ if (this._accessPointUpdateId && this._activeAc= cessPoint !=3D ap) { -+ this._activeAccessPoint.disconnect(this._ac= cessPointUpdateId); -+ this._activeAccessPoint =3D ap; -+ this._activeAccessPointUpdateId =3D ap.conn= ect('notify::strength', Lang.bind(function() { -+ this.setIcon('network-wireless-signal-'= + signalToIcon(ap.strength)); -+ })); -+ } -+ this.setIcon('network-wireless-signal-' + signa= lToIcon(ap.strength)); -+ hasApIcon =3D true; -+ } -+ break; -+ } else { -+ log('Active connection with no primary device?'); -+ break; -+ } -+ case NMConnectionCategory.WIRED: -+ this.setIcon('network-wired'); -+ break; -+ case NMConnectionCategory.WWAN: -+ dev =3D mc._primaryDevice; -+ if (!dev) { -+ log('Active connection with no primary device?'); -+ break; -+ } -+ if (!dev.mobileDevice) { -+ // this can happen for bluetooth in PAN mode -+ // XXX: need network-cellular-connected icon -+ this.setIcon('network-cellular-signal-excellent'); -+ break; -+ } =20 -+ -+ if (this._mobileUpdateId && this._mobileUpdateDevice !=3D= dev) { -+ this._mobileUpdateDevice.disconnect(this._mobileUpd= ateId); -+ this._mobileUpdateDevice =3D dev.mobileDevice; -+ this._mobileUpdateId =3D dev.mobileDevice.connect('= notify::signal-quality', Lang.bind(this, function() { -+ this.setIcon('network-cellular-signal-' + signa= lToIcon(dev.mobileDevice.signal_quality)); -+ })); -+ } -+ this.setIcon('network-cellular-signal-' + signalToIcon(= dev.mobileDevice.signal_quality)); -+ hasMobileIcon =3D true; -+ break; -+ case NMConnectionCategory.VPN: -+ this.setIcon('network-vpn'); -+ break; -+ default: -+ log('Invalid active connection type ' + mc._section); -+ this.setIcon('network-error'); -+ break; -+ } -+ } -+ -+ // cleanup stale signal connections -+ -+ if (!hasApIcon && this._activeAccessPointUpdateId) { -+ this._activeAccessPoint.disconnect(this._activeAccessPointU= pdateId); -+ this._activeAccessPoint =3D null; -+ this._activeAccessPointUpdateId =3D 0; -+ } -+ if (!hasMobileIcon && this._mobileUpdateId) { -+ this._mobileUpdateDevice.disconnect(this._mobileUpdateId); -+ this._mobileUpdateDevice =3D null; -+ this._mobileUpdateId =3D 0; -+ } -+ } -+}; -+ -+function NMMessageTraySource() { -+ this._init(); -+} -+ -+NMMessageTraySource.prototype =3D { -+ __proto__: MessageTray.Source.prototype, -+ -+ _init: function() { -+ MessageTray.Source.prototype._init.call(this, _("Network Manage= r")); -+ -+ let icon =3D new St.Icon({ icon_name: 'network-transmit-receive= ', -+ icon_type: St.IconType.SYMBOLIC, -+ icon_size: this.ICON_SIZE -+ }); -+ this._setSummaryIcon(icon); -+ } -+}; -diff --git a/src/Makefile.am b/src/Makefile.am -index 7c251de..0c440ae 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -62,7 +62,8 @@ gnome_shell_cflags =3D \ - $(GNOME_SHELL_CFLAGS) \ - -I$(srcdir)/tray \ - -DVERSION=3D\"$(VERSION)\" \ -- -DLOCALEDIR=3D\"$(datadir)/locale\" \ -+ -DLOCALEDIR=3D\"$(datadir)/locale\" \ -+ -DDATADIR=3D\"$(datadir)\" \ - -DGNOME_SHELL_LIBEXECDIR=3D\"$(libexecdir)\" \ - -DGNOME_SHELL_DATADIR=3D\"$(pkgdatadir)\" \ - -DGNOME_SHELL_PKGLIBDIR=3D\"$(pkglibdir)\" \ -@@ -90,6 +91,7 @@ shell_public_headers_h =3D \ - shell-generic-container.h \ - shell-gtk-embed.h \ - shell-global.h \ -+ shell-mobile-providers.h \ - shell-perf-log.h \ - shell-slicer.h \ - shell-stack.h \ -@@ -121,6 +123,7 @@ libgnome_shell_la_SOURCES =3D \ - shell-generic-container.c \ - shell-gtk-embed.c \ - shell-global.c \ -+ shell-mobile-providers.c \ - shell-perf-log.c \ - shell-polkit-authentication-agent.h \ - shell-polkit-authentication-agent.c \ -diff --git a/src/shell-mobile-providers.c b/src/shell-mobile-providers.c -new file mode 100644 -index 0000000..ca6a41f ---- /dev/null -+++ b/src/shell-mobile-providers.c -@@ -0,0 +1,816 @@ -+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 = -*- */ -+/* -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -+ * Boston, MA 02110-1301 USA. -+ * -+ * Copyright (C) 2009 Novell, Inc. -+ * Author: Tambet Ingo (tambet@gmail.com). -+ * -+ * Copyright (C) 2009 - 2010 Red Hat, Inc. -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "shell-mobile-providers.h" -+ -+#ifndef MOBILE_BROADBAND_PROVIDER_INFO -+#define MOBILE_BROADBAND_PROVIDER_INFO DATADIR "/mobile-broadband-provi= der-info/serviceproviders.xml" -+#endif -+ -+#define ISO_3166_COUNTRY_CODES DATADIR "/zoneinfo/iso3166.tab" -+ -+ -+ -+static GHashTable * -+read_country_codes (void) -+{ -+ GHashTable *table; -+ GIOChannel *channel; -+ GString *buffer; -+ GError *error =3D NULL; -+ GIOStatus status; -+ -+ channel =3D g_io_channel_new_file (ISO_3166_COUNTRY_CODES, "r", &er= ror); -+ if (!channel) { -+ if (error) { -+ g_warning ("Could not read " ISO_3166_COUNTRY_CODES ": %s",= error->message); -+ g_error_free (error); -+ } else -+ g_warning ("Could not read " ISO_3166_COUNTRY_CODES ": Unkn= own error"); -+ -+ return NULL; -+ } -+ -+ table =3D g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g= _free); -+ buffer =3D g_string_sized_new (32); -+ -+ status =3D G_IO_STATUS_NORMAL; -+ while (status =3D=3D G_IO_STATUS_NORMAL) { -+ status =3D g_io_channel_read_line_string (channel, buffer, NULL= , &error); -+ -+ switch (status) { -+ case G_IO_STATUS_NORMAL: -+ if (buffer->str[0] !=3D '#') { -+ char **pieces; -+ -+ pieces =3D g_strsplit (buffer->str, "\t", 2); -+ -+ /* Hack for rh#556292; iso3166.tab is just wrong */ -+ pieces[1] =3D pieces[1] ? g_strchomp (pieces[1]) : NULL= ; -+ if (pieces[1] && !strcmp (pieces[1], "Britain (UK)")) { -+ g_free (pieces[1]); -+ pieces[1] =3D g_strdup (_("United Kingdom")); -+ } -+ -+ g_hash_table_insert (table, pieces[0], pieces[1]); -+ g_free (pieces); -+ } -+ -+ g_string_truncate (buffer, 0); -+ break; -+ case G_IO_STATUS_EOF: -+ break; -+ case G_IO_STATUS_ERROR: -+ g_warning ("Error while reading: %s", error->message); -+ g_error_free (error); -+ break; -+ case G_IO_STATUS_AGAIN: -+ /* FIXME: Try again a few times, but really, it never happe= s, right? */ -+ break; -+ } -+ } -+ -+ g_string_free (buffer, TRUE); -+ g_io_channel_unref (channel); -+ -+ return table; -+} -+ -+/* XML Parser */ -+ -+typedef enum { -+ PARSER_TOPLEVEL =3D 0, -+ PARSER_COUNTRY, -+ PARSER_PROVIDER, -+ PARSER_METHOD_GSM, -+ PARSER_METHOD_GSM_APN, -+ PARSER_METHOD_CDMA, -+ PARSER_ERROR -+} MobileContextState; -+ -+typedef struct { -+ GHashTable *country_codes; -+ GHashTable *table; -+ -+ char *current_country; -+ GSList *current_providers; -+ ShellMobileProvider *current_provider; -+ ShellMobileAccessMethod *current_method; -+ -+ char *text_buffer; -+ MobileContextState state; -+} MobileParser; -+ -+static ShellGsmMccMnc * -+mcc_mnc_new (const char *mcc, const char *mnc) -+{ -+ ShellGsmMccMnc *m; -+ -+ m =3D g_slice_new (ShellGsmMccMnc); -+ m->mcc =3D g_strstrip (g_strdup (mcc)); -+ m->mnc =3D g_strstrip (g_strdup (mnc)); -+ return m; -+} -+ -+/* added in porting */ -+static ShellGsmMccMnc * -+mcc_mnc_copy (const ShellGsmMccMnc *other) { -+ ShellGsmMccMnc *ret; -+ -+ ret =3D g_slice_new (ShellGsmMccMnc); -+ ret->mcc =3D g_strdup (other->mcc); -+ ret->mnc =3D g_strdup (other->mnc); -+ return ret; -+} -+ -+static void -+mcc_mnc_free (ShellGsmMccMnc *m) -+{ -+ g_return_if_fail (m !=3D NULL); -+ g_free (m->mcc); -+ g_free (m->mnc); -+ g_slice_free (ShellGsmMccMnc, m); -+} -+ -+/* added in porting */ -+G_DEFINE_BOXED_TYPE (ShellGsmMccMnc, shell_gsm_mcc_mnc, mcc_mnc_copy, m= cc_mnc_free) -+ -+static ShellMobileAccessMethod * -+access_method_new (void) -+{ -+ ShellMobileAccessMethod *method; -+ -+ method =3D g_slice_new0 (ShellMobileAccessMethod); -+ method->refs =3D 1; -+ method->lcl_names =3D g_hash_table_new_full (g_str_hash, g_str_equa= l, -+ (GDestroyNotify) g_free, -+ (GDestroyNotify) g_free)= ; -+ -+ return method; -+} -+ -+ShellMobileAccessMethod * -+shell_mobile_access_method_ref (ShellMobileAccessMethod *method) -+{ -+ g_return_val_if_fail (method !=3D NULL, NULL); -+ g_return_val_if_fail (method->refs > 0, NULL); -+=20 -+ method->refs++; -+ -+ return method; -+} -+ -+void -+shell_mobile_access_method_unref (ShellMobileAccessMethod *method) -+{ -+ g_return_if_fail (method !=3D NULL); -+ g_return_if_fail (method->refs > 0); -+ -+ if (--method->refs =3D=3D 0) { -+ g_free (method->name); -+ g_hash_table_destroy (method->lcl_names); -+ g_free (method->username); -+ g_free (method->password); -+ g_free (method->gateway); -+ g_free (method->gsm_apn); -+ g_slist_foreach (method->dns, (GFunc) g_free, NULL); -+ g_slist_free (method->dns); -+ -+ g_slice_free (ShellMobileAccessMethod, method); -+ } -+} -+ -+GType -+shell_mobile_access_method_get_type (void) -+{ -+ static GType type =3D 0; -+ -+ if (G_UNLIKELY (type =3D=3D 0)) { -+ type =3D g_boxed_type_register_static ("ShellMobileAccessMethod= ", -+ (GBoxedCopyFunc) shell_mob= ile_access_method_ref, -+ (GBoxedFreeFunc) shell_mob= ile_access_method_unref); -+ } -+ return type; -+} -+ -+ -+static ShellMobileProvider * -+provider_new (void) -+{ -+ ShellMobileProvider *provider; -+ -+ provider =3D g_slice_new0 (ShellMobileProvider); -+ provider->refs =3D 1; -+ provider->lcl_names =3D g_hash_table_new_full (g_str_hash, g_str_eq= ual, -+ (GDestroyNotify) g_fre= e, -+ (GDestroyNotify) g_fre= e); -+ -+ return provider; -+} -+ -+ShellMobileProvider * -+shell_mobile_provider_ref (ShellMobileProvider *provider) -+{ -+ provider->refs++; -+ -+ return provider; -+} -+ -+void -+shell_mobile_provider_unref (ShellMobileProvider *provider) -+{ -+ if (--provider->refs =3D=3D 0) { -+ g_free (provider->name); -+ g_hash_table_destroy (provider->lcl_names); -+ -+ g_slist_foreach (provider->methods, (GFunc) shell_mobile_access= _method_unref, NULL); -+ g_slist_free (provider->methods); -+ -+ g_slist_foreach (provider->gsm_mcc_mnc, (GFunc) mcc_mnc_free, N= ULL); -+ g_slist_free (provider->gsm_mcc_mnc); -+ -+ g_slist_free (provider->cdma_sid); -+ -+ g_slice_free (ShellMobileProvider, provider); -+ } -+} -+ -+GType -+shell_mobile_provider_get_type (void) -+{ -+ static GType type =3D 0; -+ -+ if (G_UNLIKELY (type =3D=3D 0)) { -+ type =3D g_boxed_type_register_static ("ShellMobileProvider", -+ (GBoxedCopyFunc) shell_mob= ile_provider_ref, -+ (GBoxedFreeFunc) shell_mob= ile_provider_unref); -+ } -+ return type; -+} -+ -+static void -+provider_list_free (gpointer data) -+{ -+ GSList *list =3D (GSList *) data; -+ -+ while (list) { -+ shell_mobile_provider_unref ((ShellMobileProvider *) list->data= ); -+ list =3D g_slist_delete_link (list, list); -+ } -+} -+ -+static void -+parser_toplevel_start (MobileParser *parser, -+ const char *name, -+ const char **attribute_names, -+ const char **attribute_values) -+{ -+ int i; -+ -+ if (!strcmp (name, "serviceproviders")) { -+ for (i =3D 0; attribute_names && attribute_names[i]; i++) { -+ if (!strcmp (attribute_names[i], "format")) { -+ if (strcmp (attribute_values[i], "2.0")) { -+ g_warning ("%s: mobile broadband provider database = format '%s'" -+ " not supported.", __func__, attribute_v= alues[i]); -+ parser->state =3D PARSER_ERROR; -+ break; -+ } -+ } -+ } -+ } else if (!strcmp (name, "country")) { -+ for (i =3D 0; attribute_names && attribute_names[i]; i++) { -+ if (!strcmp (attribute_names[i], "code")) { -+ char *country_code; -+ char *country; -+ -+ country_code =3D g_ascii_strup (attribute_values[i], -1= ); -+ country =3D g_hash_table_lookup (parser->country_codes,= country_code); -+ if (country) { -+ parser->current_country =3D g_strdup (country); -+ g_free (country_code); -+ } else -+ parser->current_country =3D country_code; -+ -+ parser->state =3D PARSER_COUNTRY; -+ break; -+ } -+ } -+ } -+} -+ -+static void -+parser_country_start (MobileParser *parser, -+ const char *name, -+ const char **attribute_names, -+ const char **attribute_values) -+{ -+ if (!strcmp (name, "provider")) { -+ parser->state =3D PARSER_PROVIDER; -+ parser->current_provider =3D provider_new (); -+ } -+} -+ -+static void -+parser_provider_start (MobileParser *parser, -+ const char *name, -+ const char **attribute_names, -+ const char **attribute_values) -+{ -+ if (!strcmp (name, "gsm")) -+ parser->state =3D PARSER_METHOD_GSM; -+ else if (!strcmp (name, "cdma")) { -+ parser->state =3D PARSER_METHOD_CDMA; -+ parser->current_method =3D access_method_new (); -+ } -+} -+ -+static void -+parser_gsm_start (MobileParser *parser, -+ const char *name, -+ const char **attribute_names, -+ const char **attribute_values) -+{ -+ if (!strcmp (name, "network-id")) { -+ const char *mcc =3D NULL, *mnc =3D NULL; -+ int i; -+ -+ for (i =3D 0; attribute_names && attribute_names[i]; i++) { -+ if (!strcmp (attribute_names[i], "mcc")) -+ mcc =3D attribute_values[i]; -+ else if (!strcmp (attribute_names[i], "mnc")) -+ mnc =3D attribute_values[i]; -+ -+ if (mcc && strlen (mcc) && mnc && strlen (mnc)) { -+ parser->current_provider->gsm_mcc_mnc =3D g_slist_prepe= nd (parser->current_provider->gsm_mcc_mnc, -+ = mcc_mnc_new (mcc, mnc)); -+ break; -+ } -+ } -+ } else if (!strcmp (name, "apn")) { -+ int i; -+ -+ for (i =3D 0; attribute_names && attribute_names[i]; i++) { -+ if (!strcmp (attribute_names[i], "value")) { -+ -+ parser->state =3D PARSER_METHOD_GSM_APN; -+ parser->current_method =3D access_method_new (); -+ parser->current_method->gsm_apn =3D g_strstrip (g_strdu= p (attribute_values[i])); -+ break; -+ } -+ } -+ } -+} -+ -+static void -+parser_cdma_start (MobileParser *parser, -+ const char *name, -+ const char **attribute_names, -+ const char **attribute_values) -+{ -+ if (!strcmp (name, "sid")) { -+ int i; -+ -+ for (i =3D 0; attribute_names && attribute_names[i]; i++) { -+ if (!strcmp (attribute_names[i], "value")) { -+ unsigned long tmp; -+ -+ errno =3D 0; -+ tmp =3D strtoul (attribute_values[i], NULL, 10); -+ if (errno =3D=3D 0 && tmp > 0) -+ parser->current_provider->cdma_sid =3D g_slist_prep= end (parser->current_provider->cdma_sid, -+ = GUINT_TO_POINTER ((guint32) tmp)); -+ break; -+ } -+ } -+ } -+} -+ -+static void -+mobile_parser_start_element (GMarkupParseContext *context, -+ const gchar *element_name, -+ const gchar **attribute_names, -+ const gchar **attribute_values, -+ gpointer data, -+ GError **error) -+{ -+ MobileParser *parser =3D (MobileParser *) data; -+ -+ if (parser->text_buffer) { -+ g_free (parser->text_buffer); -+ parser->text_buffer =3D NULL; -+ } -+ -+ switch (parser->state) { -+ case PARSER_TOPLEVEL: -+ parser_toplevel_start (parser, element_name, attribute_names, a= ttribute_values); -+ break; -+ case PARSER_COUNTRY: -+ parser_country_start (parser, element_name, attribute_names, at= tribute_values); -+ break; -+ case PARSER_PROVIDER: -+ parser_provider_start (parser, element_name, attribute_names, a= ttribute_values); -+ break; -+ case PARSER_METHOD_GSM: -+ parser_gsm_start (parser, element_name, attribute_names, attrib= ute_values); -+ break; -+ case PARSER_METHOD_CDMA: -+ parser_cdma_start (parser, element_name, attribute_names, attri= bute_values); -+ break; -+ default: -+ break; -+ } -+} -+ -+static void -+parser_country_end (MobileParser *parser, -+ const char *name) -+{ -+ if (!strcmp (name, "country")) { -+ g_hash_table_insert (parser->table, parser->current_country, pa= rser->current_providers); -+ parser->current_country =3D NULL; -+ parser->current_providers =3D NULL; -+ parser->text_buffer =3D NULL; -+ parser->state =3D PARSER_TOPLEVEL; -+ } -+} -+ -+static void -+parser_provider_end (MobileParser *parser, -+ const char *name) -+{ -+ if (!strcmp (name, "name")) { -+ if (!parser->current_provider->name) { -+ /* Use the first one. */ -+ parser->current_provider->name =3D parser->text_buffer; -+ parser->text_buffer =3D NULL; -+ } -+ } else if (!strcmp (name, "provider")) { -+ parser->current_provider->methods =3D g_slist_reverse (parser->= current_provider->methods); -+ -+ parser->current_provider->gsm_mcc_mnc =3D g_slist_reverse (pars= er->current_provider->gsm_mcc_mnc); -+ parser->current_provider->cdma_sid =3D g_slist_reverse (parser-= >current_provider->cdma_sid); -+ -+ parser->current_providers =3D g_slist_prepend (parser->current_= providers, parser->current_provider); -+ parser->current_provider =3D NULL; -+ parser->text_buffer =3D NULL; -+ parser->state =3D PARSER_COUNTRY; -+ } -+} -+ -+static void -+parser_gsm_end (MobileParser *parser, -+ const char *name) -+{ -+ if (!strcmp (name, "gsm")) { -+ parser->text_buffer =3D NULL; -+ parser->state =3D PARSER_PROVIDER; -+ } -+} -+ -+static void -+parser_gsm_apn_end (MobileParser *parser, -+ const char *name) -+{ -+ if (!strcmp (name, "name")) { -+ if (!parser->current_method->name) { -+ /* Use the first one. */ -+ parser->current_method->name =3D parser->text_buffer; -+ parser->text_buffer =3D NULL; -+ } -+ } else if (!strcmp (name, "username")) { -+ parser->current_method->username =3D parser->text_buffer; -+ parser->text_buffer =3D NULL; -+ } else if (!strcmp (name, "password")) { -+ parser->current_method->password =3D parser->text_buffer; -+ parser->text_buffer =3D NULL; -+ } else if (!strcmp (name, "dns")) { -+ parser->current_method->dns =3D g_slist_prepend (parser->curren= t_method->dns, parser->text_buffer); -+ parser->text_buffer =3D NULL; -+ } else if (!strcmp (name, "gateway")) { -+ parser->current_method->gateway =3D parser->text_buffer; -+ parser->text_buffer =3D NULL; -+ } else if (!strcmp (name, "apn")) { -+ parser->current_method->type =3D SHELL_MOBILE_ACCESS_METHOD_TYP= E_GSM; -+ parser->current_method->dns =3D g_slist_reverse (parser->curren= t_method->dns); -+ -+ if (!parser->current_method->name) -+ parser->current_method->name =3D g_strdup (_("Default")); -+ -+ parser->current_provider->methods =3D g_slist_prepend (parser->= current_provider->methods, -+ parser->cu= rrent_method); -+ parser->current_method =3D NULL; -+ parser->text_buffer =3D NULL; -+ parser->state =3D PARSER_METHOD_GSM; -+ } -+} -+ -+static void -+parser_cdma_end (MobileParser *parser, -+ const char *name) -+{ -+ if (!strcmp (name, "username")) { -+ parser->current_method->username =3D parser->text_buffer; -+ parser->text_buffer =3D NULL; -+ } else if (!strcmp (name, "password")) { -+ parser->current_method->password =3D parser->text_buffer; -+ parser->text_buffer =3D NULL; -+ } else if (!strcmp (name, "dns")) { -+ parser->current_method->dns =3D g_slist_prepend (parser->curren= t_method->dns, parser->text_buffer); -+ parser->text_buffer =3D NULL; -+ } else if (!strcmp (name, "gateway")) { -+ parser->current_method->gateway =3D parser->text_buffer; -+ parser->text_buffer =3D NULL; -+ } else if (!strcmp (name, "cdma")) { -+ parser->current_method->type =3D SHELL_MOBILE_ACCESS_METHOD_TYP= E_CDMA; -+ parser->current_method->dns =3D g_slist_reverse (parser->curren= t_method->dns); -+ -+ if (!parser->current_method->name) -+ parser->current_method->name =3D g_strdup (parser->current_= provider->name); -+ -+ parser->current_provider->methods =3D g_slist_prepend (parser->= current_provider->methods, -+ parser->cu= rrent_method); -+ parser->current_method =3D NULL; -+ parser->text_buffer =3D NULL; -+ parser->state =3D PARSER_PROVIDER; -+ } -+} -+ -+static void -+mobile_parser_end_element (GMarkupParseContext *context, -+ const gchar *element_name, -+ gpointer data, -+ GError **error) -+{ -+ MobileParser *parser =3D (MobileParser *) data; -+ -+ switch (parser->state) { -+ case PARSER_COUNTRY: -+ parser_country_end (parser, element_name); -+ break; -+ case PARSER_PROVIDER: -+ parser_provider_end (parser, element_name); -+ break; -+ case PARSER_METHOD_GSM: -+ parser_gsm_end (parser, element_name); -+ break; -+ case PARSER_METHOD_GSM_APN: -+ parser_gsm_apn_end (parser, element_name); -+ break; -+ case PARSER_METHOD_CDMA: -+ parser_cdma_end (parser, element_name); -+ break; -+ default: -+ break; -+ } -+} -+ -+static void -+mobile_parser_characters (GMarkupParseContext *context, -+ const gchar *text, -+ gsize text_len, -+ gpointer data, -+ GError **error) -+{ -+ MobileParser *parser =3D (MobileParser *) data; -+ -+ g_free (parser->text_buffer); -+ parser->text_buffer =3D g_strdup (text); -+} -+ -+static const GMarkupParser mobile_parser =3D { -+ mobile_parser_start_element, -+ mobile_parser_end_element, -+ mobile_parser_characters, -+ NULL, /* passthrough */ -+ NULL /* error */ -+}; -+ -+/** -+ * shell_mobile_providers_parse: -+ * @out_ccs: (out) (allow-none): (element-type utf8 utf8): a #GHashTabl= e containing -+ * country codes -+ * -+ * Returns: (element-type utf8 GList) (transfer c= ontainer): a -+ * hash table where keys are country names 'char *', values are a 'GS= List *' -+ * of 'ShellMobileProvider *'. Everything is destroyed with g_hash_ta= ble_destroy (). -+*/ -+GHashTable * -+shell_mobile_providers_parse (GHashTable **out_ccs) -+{ -+ GMarkupParseContext *ctx; -+ GIOChannel *channel; -+ MobileParser parser; -+ GError *error =3D NULL; -+ char buffer[4096]; -+ GIOStatus status; -+ gsize len =3D 0; -+ -+ memset (&parser, 0, sizeof (MobileParser)); -+ -+ parser.country_codes =3D read_country_codes (); -+ if (!parser.country_codes) -+ goto out; -+ -+ channel =3D g_io_channel_new_file (MOBILE_BROADBAND_PROVIDER_INFO, = "r", &error); -+ if (!channel) { -+ if (error) { -+ g_warning ("Could not read " MOBILE_BROADBAND_PROVIDER_INFO= ": %s", error->message); -+ g_error_free (error); -+ } else -+ g_warning ("Could not read " MOBILE_BROADBAND_PROVIDER_INFO= ": Unknown error"); -+ -+ goto out; -+ } -+ -+ parser.table =3D g_hash_table_new_full (g_str_hash, g_str_equal, g_= free, provider_list_free); -+ parser.state =3D PARSER_TOPLEVEL; -+ -+ ctx =3D g_markup_parse_context_new (&mobile_parser, 0, &parser, NUL= L); -+ -+ status =3D G_IO_STATUS_NORMAL; -+ while (status =3D=3D G_IO_STATUS_NORMAL) { -+ status =3D g_io_channel_read_chars (channel, buffer, sizeof (bu= ffer), &len, &error); -+ -+ switch (status) { -+ case G_IO_STATUS_NORMAL: -+ if (!g_markup_parse_context_parse (ctx, buffer, len, &error= )) { -+ status =3D G_IO_STATUS_ERROR; -+ g_warning ("Error while parsing XML: %s", error->messag= e); -+ g_error_free (error);; -+ } -+ break; -+ case G_IO_STATUS_EOF: -+ break; -+ case G_IO_STATUS_ERROR: -+ g_warning ("Error while reading: %s", error->message); -+ g_error_free (error); -+ break; -+ case G_IO_STATUS_AGAIN: -+ /* FIXME: Try again a few times, but really, it never happe= s, right? */ -+ break; -+ } -+ } -+ -+ g_io_channel_unref (channel); -+ g_markup_parse_context_free (ctx); -+ -+ if (parser.current_provider) { -+ g_warning ("pending current provider"); -+ shell_mobile_provider_unref (parser.current_provider); -+ } -+ -+ if (parser.current_providers) { -+ g_warning ("pending current providers"); -+ provider_list_free (parser.current_providers); -+ } -+ -+ g_free (parser.current_country); -+ g_free (parser.text_buffer); -+ -+ out: -+ if (parser.country_codes) { -+ if (out_ccs) -+ *out_ccs =3D parser.country_codes; -+ else -+ g_hash_table_destroy (parser.country_codes); -+ } -+ -+ return parser.table; -+} -+ -+static void -+dump_generic (ShellMobileAccessMethod *method) -+{ -+ GSList *iter; -+ GString *dns; -+ -+ g_print (" username: %s\n", method->username ? method->usern= ame : ""); -+ g_print (" password: %s\n", method->password ? method->passw= ord : ""); -+ -+ dns =3D g_string_new (NULL); -+ for (iter =3D method->dns; iter; iter =3D g_slist_next (iter)) -+ g_string_append_printf (dns, "%s%s", dns->len ? ", " : "", (cha= r *) iter->data); -+ g_print (" dns : %s\n", dns->str); -+ g_string_free (dns, TRUE); -+ -+ g_print (" gateway : %s\n", method->gateway ? method->gatewa= y : ""); -+} -+ -+static void -+dump_cdma (ShellMobileAccessMethod *method) -+{ -+ g_print (" CDMA: %s\n", method->name); -+ -+ dump_generic (method); -+} -+ -+static void -+dump_gsm (ShellMobileAccessMethod *method) -+{ -+ g_print (" APN: %s (%s)\n", method->name, method->gsm_apn); -+ -+ dump_generic (method); -+} -+ -+static void -+dump_country (gpointer key, gpointer value, gpointer user_data) -+{ -+ GSList *citer, *miter; -+ -+ for (citer =3D value; citer; citer =3D g_slist_next (citer)) { -+ ShellMobileProvider *provider =3D citer->data; -+ -+ g_print ("Provider: %s (%s)\n", provider->name, (const char *) = key); -+ for (miter =3D provider->methods; miter; miter =3D g_slist_next= (miter)) { -+ ShellMobileAccessMethod *method =3D miter->data; -+ GSList *liter; -+ -+ -+ for (liter =3D provider->gsm_mcc_mnc; liter; liter =3D g_sl= ist_next (liter)) { -+ ShellGsmMccMnc *m =3D liter->data; -+ g_print (" MCC/MNC: %s-%s\n", m->mcc, m->mnc); -+ } -+ -+ for (liter =3D provider->cdma_sid; liter; liter =3D g_slist= _next (liter)) -+ g_print (" SID: %d\n", GPOINTER_TO_UINT (liter->= data)); -+ -+ switch (method->type) { -+ case SHELL_MOBILE_ACCESS_METHOD_TYPE_CDMA: -+ dump_cdma (method); -+ break; -+ case SHELL_MOBILE_ACCESS_METHOD_TYPE_GSM: -+ dump_gsm (method); -+ break; -+ default: -+ break; -+ } -+ g_print ("\n"); -+ } -+ } -+} -+ -+void -+shell_mobile_providers_dump (GHashTable *providers) -+{ -+ g_return_if_fail (providers !=3D NULL); -+ g_hash_table_foreach (providers, dump_country, NULL); -+} -+ -+/* All the following don't exist in nm-applet, because C doesn't need -+ those. They're only needed for the introspection annotations -+*/ -+ -+/** -+ * shell_mobile_provider_get_gsm_mcc_mnc: -+ * @provider: a #ShellMobileProvider -+ * -+ * Returns: (element-type Shell.GsmMccMnc) (transfer none): the -+ * list of #ShellGsmMccMnc this provider exposes -+ */ -+GSList * -+shell_mobile_provider_get_gsm_mcc_mnc (ShellMobileProvider *provider) -+{ -+ return provider->gsm_mcc_mnc; -+} -+ -+/** -+ * shell_mobile_provider_get_cdma_sid: -+ * @provider: a #ShellMobileProvider -+ * -+ * Returns: (element-type guint32) (transfer none): the -+ * list of CDMA sids this provider exposes -+ */ -+GSList * -+shell_mobile_provider_get_cdma_sid (ShellMobileProvider *provider) -+{ -+ return provider->cdma_sid; -+} -diff --git a/src/shell-mobile-providers.h b/src/shell-mobile-providers.h -new file mode 100644 -index 0000000..d70b8e2 ---- /dev/null -+++ b/src/shell-mobile-providers.h -@@ -0,0 +1,96 @@ -+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 = -*- */ -+/* -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -+ * Boston, MA 02110-1301 USA. -+ * -+ * Copyright (C) 2009 Novell, Inc. -+ * Author: Tambet Ingo (tambet@gmail.com). -+ * -+ * Copyright (C) 2009 - 2010 Red Hat, Inc. -+ * -+ * Ported to GNOME Shell by Giovanni Campagna -+ * Porting consisted only in replacing nmn with shell, to be compatible= with -+ * GObject Introspection namespacing -+ */ -+ -+#ifndef SHELL_MOBILE_PROVIDERS_H -+#define SHELL_MOBILE_PROVIDERS_H -+ -+#include -+#include -+ -+#define SHELL_TYPE_MOBILE_PROVIDER (shell_mobile_provider_get_type ()) -+#define SHELL_TYPE_MOBILE_ACCESS_METHOD (shell_mobile_access_method_get= _type ()) -+ -+typedef enum { -+ SHELL_MOBILE_ACCESS_METHOD_TYPE_UNKNOWN =3D 0, -+ SHELL_MOBILE_ACCESS_METHOD_TYPE_GSM, -+ SHELL_MOBILE_ACCESS_METHOD_TYPE_CDMA -+} ShellMobileAccessMethodType; -+ -+typedef struct { -+ char *mcc; -+ char *mnc; -+} ShellGsmMccMnc; -+ -+typedef struct { -+ char *name; -+ /* maps lang (char *) -> name (char *) */ -+ GHashTable *lcl_names; -+ -+ char *username; -+ char *password; -+ char *gateway; -+ GSList *dns; /* GSList of 'char *' */ -+ -+ /* Only used with SHELL_PROVIDER_TYPE_GSM */ -+ char *gsm_apn; -+ -+ ShellMobileAccessMethodType type; -+ -+ gint refs; -+} ShellMobileAccessMethod; -+ -+typedef struct { -+ char *name; -+ /* maps lang (char *) -> name (char *) */ -+ GHashTable *lcl_names; -+ -+ GSList *methods; /* GSList of ShellMobileAccessMethod */ -+ -+ GSList *gsm_mcc_mnc; /* GSList of ShellGsmMccMnc */ -+ GSList *cdma_sid; /* GSList of guint32 */ -+ -+ gint refs; -+} ShellMobileProvider; -+ -+ -+GType shell_gsm_mcc_mnc_get_type (void); /* added in porting */ -+GType shell_mobile_provider_get_type (void); -+GType shell_mobile_access_method_get_type (void); -+ -+ShellMobileProvider *shell_mobile_provider_ref (ShellMobileProvider *= provider); -+void shell_mobile_provider_unref (ShellMobileProvider *= provider); -+GSList * shell_mobile_provider_get_gsm_mcc_mnc (ShellMobile= Provider *provider); -+GSList * shell_mobile_provider_get_cdma_sid (ShellMobilePro= vider *provider); -+ -+ShellMobileAccessMethod *shell_mobile_access_method_ref (ShellMobileA= ccessMethod *method); -+void shell_mobile_access_method_unref (ShellMobileA= ccessMethod *method); -+ -+GHashTable *shell_mobile_providers_parse (GHashTable **out_ccs); -+ -+void shell_mobile_providers_dump (GHashTable *providers); -+ -+#endif /* SHELL_MOBILE_PROVIDERS_H */ -diff --git a/tools/build/gnome-shell.modules b/tools/build/gnome-shell.m= odules -index 6c8db09..837cb22 100644 ---- a/tools/build/gnome-shell.modules -+++ b/tools/build/gnome-shell.modules -@@ -9,6 +9,8 @@ - href=3D"git://git.gnome.org/"/> - -+ - - - -=20 -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - ---=20 -1.7.4 \ No newline at end of file diff --git a/gnome-base/gnome-shell/gnome-shell-9999.ebuild b/gnome-base/= gnome-shell/gnome-shell-9999.ebuild index 17a9912..bc58dac 100644 --- a/gnome-base/gnome-shell/gnome-shell-9999.ebuild +++ b/gnome-base/gnome-shell/gnome-shell-9999.ebuild @@ -13,7 +13,7 @@ HOMEPAGE=3D"http://live.gnome.org/GnomeShell" =20 LICENSE=3D"GPL-2" SLOT=3D"0" -IUSE=3D"nm-applet" +IUSE=3D"+nm-applet" if [[ ${PV} =3D 9999 ]]; then inherit gnome2-live KEYWORDS=3D"" @@ -23,7 +23,7 @@ fi =20 # gnome-desktop-2.91.2 is needed due to header changes, db82a33 in gnome= -desktop # FIXME: Automagic gnome-bluetooth[introspection] support. -# latest mutter is needed due to commit 474ff2e997 +# latest mutter is needed due to commit 474ff2e9 and commit 079953c3 # latest gsettings-desktop-schemas is needed due to commit 602fa1c6 COMMON_DEPEND=3D">=3Ddev-libs/glib-2.25.9:2 >=3Ddev-libs/gjs-0.7.11 @@ -40,7 +40,7 @@ COMMON_DEPEND=3D">=3Ddev-libs/glib-2.25.9:2 >=3Dnet-libs/telepathy-glib-0.13.12[introspection] >=3Dnet-wireless/gnome-bluetooth-2.90.0[introspection] >=3Dsys-auth/polkit-0.100[introspection] - >=3Dx11-wm/mutter-2.91.91[introspection] + >=3Dx11-wm/mutter-2.91.91.1[introspection] =20 dev-libs/dbus-glib dev-libs/libxml2:2 @@ -55,9 +55,7 @@ COMMON_DEPEND=3D">=3Ddev-libs/glib-2.25.9:2 =20 x11-libs/startup-notification x11-libs/libXfixes - x11-apps/mesa-progs - - nm-applet? ( >=3Dnet-misc/networkmanager-0.8.996[introspection] )" + x11-apps/mesa-progs" # Runtime-only deps are probably incomplete and approximate. # Each block: # 1. Pull in polkit-0.101 for pretty authorization dialogs @@ -77,7 +75,9 @@ RDEPEND=3D"${COMMON_DEPEND} >=3Dgnome-base/gnome-settings-daemon-2.91 >=3Dgnome-base/gnome-control-center-2.91 =20 - nm-applet? ( >=3Dgnome-extra/nm-applet-0.8.996 )" + nm-applet? ( + >=3Dgnome-extra/nm-applet-0.8.996 + >=3Dnet-misc/networkmanager-0.8.996-r1[introspection] )" DEPEND=3D"${COMMON_DEPEND} sys-devel/gettext >=3Ddev-util/pkgconfig-0.22 @@ -90,14 +90,6 @@ G2CONF=3D"--enable-compile-warnings=3Dmaximum --disable-jhbuild-wrapper-script" =20 src_prepare() { - if use nm-applet; then - # See https://bugzilla.gnome.org/show_bug.cgi?id=3D621707" - ewarn "Adding support for the experimental NetworkManager applet." - ewarn "This needs the latest NetworkManager & nm-applet trunk." - ewarn "Report bugs about this to 'nirbheek' on #gentoo-desktop @ FreeN= ode." - epatch "${FILESDIR}/${PN}-experimental-nm-applet-1.5.patch" - fi - epatch "${FILESDIR}/${PN}-fix-gnome-bluetooth.patch" =20 gnome2_src_prepare diff --git a/net-misc/networkmanager/files/networkmanager-0.8.996-fix-int= rospection.patch b/net-misc/networkmanager/files/networkmanager-0.8.996-f= ix-introspection.patch new file mode 100644 index 0000000..0e488c3 --- /dev/null +++ b/net-misc/networkmanager/files/networkmanager-0.8.996-fix-introspect= ion.patch @@ -0,0 +1,51 @@ +From 3ac6aa8008970b9cbafaa7a7134c9dc2f455d2f7 Mon Sep 17 00:00:00 2001 +From: Giovanni Campagna +Date: Tue, 15 Mar 2011 20:37:29 +0100 +Subject: [PATCH] include: mark flags as such + +If the /*< flags >*/ annotation is missing, enums are picked as +enumerations, so bindings won't allow passing combinations of them. + +https://bugzilla.gnome.org/show_bug.cgi?id=3D643011 +--- + include/NetworkManager.h | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/include/NetworkManager.h b/include/NetworkManager.h +index d8f29c5..d421aff 100644 +--- a/include/NetworkManager.h ++++ b/include/NetworkManager.h +@@ -138,6 +138,7 @@ typedef enum { +=20 + /* 802.11 Access Point flags */ + typedef enum { ++ /*< flags >*/ + NM_802_11_AP_FLAGS_NONE =3D 0x00000000, + NM_802_11_AP_FLAGS_PRIVACY =3D 0x00000001 + } NM80211ApFlags; +@@ -150,6 +151,7 @@ typedef enum { + * information elements. + */ + typedef enum { ++ /*< flags >*/ + NM_802_11_AP_SEC_NONE =3D 0x00000000, + NM_802_11_AP_SEC_PAIR_WEP40 =3D 0x00000001, + NM_802_11_AP_SEC_PAIR_WEP104 =3D 0x00000002, +@@ -183,6 +185,7 @@ typedef enum { + * Bluetooth device. + */ + typedef enum { ++ /*< flags >*/ + NM_BT_CAPABILITY_NONE =3D 0x00000000, + NM_BT_CAPABILITY_DUN =3D 0x00000001, + NM_BT_CAPABILITY_NAP =3D 0x00000002, +@@ -205,6 +208,7 @@ typedef enum { + * API. + */ + typedef enum { ++ /*< flags >*/ + NM_DEVICE_MODEM_CAPABILITY_NONE =3D 0x00000000, + NM_DEVICE_MODEM_CAPABILITY_POTS =3D 0x00000001, + NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO =3D 0x00000002, +--=20 +1.7.4 \ No newline at end of file diff --git a/net-misc/networkmanager/networkmanager-0.8.996.ebuild b/net-= misc/networkmanager/networkmanager-0.8.996-r1.ebuild similarity index 96% rename from net-misc/networkmanager/networkmanager-0.8.996.ebuild rename to net-misc/networkmanager/networkmanager-0.8.996-r1.ebuild index a5a6587..f384197 100644 --- a/net-misc/networkmanager/networkmanager-0.8.996.ebuild +++ b/net-misc/networkmanager/networkmanager-0.8.996-r1.ebuild @@ -88,6 +88,10 @@ src_prepare() { # disable tests epatch "${FILESDIR}/${PN}-fix-tests.patch" =20 + # https://bugzilla.gnome.org/show_bug.cgi?id=3D643011 + # Merged upstream, not needed for next release + epatch "${FILESDIR}/${P}-fix-introspection.patch" + EPATCH_SOURCE=3D"${WORKDIR}/ifnet-0.9" EPATCH_SUFFIX=3D"diff" EPATCH_FO= RCE=3D"yes" epatch eautoreconf default