NetworkManager: show portal logins when required
Listen to changes in connectivity, and ask our helper to authenticate when needed. We don't have a URL to connect to yet (we will have when the new NM API lands), so we use the default of trying www.gnome.org (which is also more reliable because we can recognize when the login is done) https://bugzilla.gnome.org/show_bug.cgi?id=704416
This commit is contained in:
parent
8c67a70db0
commit
47c9243271
@ -44,6 +44,33 @@ const NM80211Mode = NetworkManager['80211Mode'];
|
|||||||
const NM80211ApFlags = NetworkManager['80211ApFlags'];
|
const NM80211ApFlags = NetworkManager['80211ApFlags'];
|
||||||
const NM80211ApSecurityFlags = NetworkManager['80211ApSecurityFlags'];
|
const NM80211ApSecurityFlags = NetworkManager['80211ApSecurityFlags'];
|
||||||
|
|
||||||
|
const PortalHelperResult = {
|
||||||
|
CANCELLED: 0,
|
||||||
|
COMPLETED: 1,
|
||||||
|
RECHECK: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
const PortalHelperIface = '<node> \
|
||||||
|
<interface name="org.gnome.Shell.PortalHelper"> \
|
||||||
|
<method name="Authenticate"> \
|
||||||
|
<arg type="o" direction="in" name="connection" /> \
|
||||||
|
<arg type="s" direction="in" name="url" /> \
|
||||||
|
<arg type="u" direction="in" name="timestamp" /> \
|
||||||
|
</method> \
|
||||||
|
<method name="Close"> \
|
||||||
|
<arg type="o" direction="in" name="connection" /> \
|
||||||
|
</method> \
|
||||||
|
<method name="Refresh"> \
|
||||||
|
<arg type="o" direction="in" name="connection" /> \
|
||||||
|
</method> \
|
||||||
|
<signal name="Done"> \
|
||||||
|
<arg type="o" name="connection" /> \
|
||||||
|
<arg type="u" name="result" /> \
|
||||||
|
</signal> \
|
||||||
|
</interface> \
|
||||||
|
</node>';
|
||||||
|
const PortalHelperProxy = Gio.DBusProxy.makeProxyWrapper(PortalHelperIface);
|
||||||
|
|
||||||
function ssidCompare(one, two) {
|
function ssidCompare(one, two) {
|
||||||
if (!one || !two)
|
if (!one || !two)
|
||||||
return false;
|
return false;
|
||||||
@ -1581,6 +1608,7 @@ const NMApplet = new Lang.Class({
|
|||||||
|
|
||||||
this._activeConnections = [ ];
|
this._activeConnections = [ ];
|
||||||
this._connections = [ ];
|
this._connections = [ ];
|
||||||
|
this._connectivityQueue = [ ];
|
||||||
|
|
||||||
this._mainConnection = null;
|
this._mainConnection = null;
|
||||||
this._mainConnectionIconChangedId = 0;
|
this._mainConnectionIconChangedId = 0;
|
||||||
@ -1609,6 +1637,7 @@ const NMApplet = new Lang.Class({
|
|||||||
this._client.connect('notify::primary-connection', Lang.bind(this, this._syncMainConnection));
|
this._client.connect('notify::primary-connection', Lang.bind(this, this._syncMainConnection));
|
||||||
this._client.connect('notify::activating-connection', Lang.bind(this, this._syncMainConnection));
|
this._client.connect('notify::activating-connection', Lang.bind(this, this._syncMainConnection));
|
||||||
this._client.connect('notify::active-connections', Lang.bind(this, this._syncVPNConnections));
|
this._client.connect('notify::active-connections', Lang.bind(this, this._syncVPNConnections));
|
||||||
|
this._client.connect('notify::connectivity', Lang.bind(this, this._syncConnectivity));
|
||||||
this._client.connect('device-added', Lang.bind(this, this._deviceAdded));
|
this._client.connect('device-added', Lang.bind(this, this._deviceAdded));
|
||||||
this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved));
|
this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved));
|
||||||
this._settings.connect('new-connection', Lang.bind(this, this._newConnection));
|
this._settings.connect('new-connection', Lang.bind(this, this._newConnection));
|
||||||
@ -1777,6 +1806,7 @@ const NMApplet = new Lang.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._updateIcon();
|
this._updateIcon();
|
||||||
|
this._syncConnectivity();
|
||||||
},
|
},
|
||||||
|
|
||||||
_syncVPNConnections: function() {
|
_syncVPNConnections: function() {
|
||||||
@ -1882,6 +1912,97 @@ const NMApplet = new Lang.Class({
|
|||||||
_syncNMState: function() {
|
_syncNMState: function() {
|
||||||
this.indicators.visible = this._client.manager_running;
|
this.indicators.visible = this._client.manager_running;
|
||||||
this.menu.actor.visible = this._client.networking_enabled;
|
this.menu.actor.visible = this._client.networking_enabled;
|
||||||
|
|
||||||
|
this._syncConnectivity();
|
||||||
|
},
|
||||||
|
|
||||||
|
_flushConnectivityQueue: function() {
|
||||||
|
if (this._portalHelperProxy) {
|
||||||
|
for (let item of this._connectivityQueue)
|
||||||
|
this._portalHelperProxy.CloseRemote(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._connectivityQueue = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
_closeConnectivityCheck: function(path) {
|
||||||
|
let index = this._connectivityQueue.indexOf(path);
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
if (this._portalHelperProxy)
|
||||||
|
this._portalHelperProxy.CloseRemote(path);
|
||||||
|
|
||||||
|
this._connectivityQueue.splice(index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_portalHelperDone: function(proxy, emitter, parameters) {
|
||||||
|
let [path, result] = parameters;
|
||||||
|
|
||||||
|
if (result == PortalHelperResult.CANCELLED) {
|
||||||
|
// Keep the connection in the queue, so the user is not
|
||||||
|
// spammed with more logins until we next flush the queue,
|
||||||
|
// which will happen once he chooses a better connection
|
||||||
|
// or we get to full connectivity through other means
|
||||||
|
} else if (result == PortalHelperResult.COMPLETED) {
|
||||||
|
this._closeConnectivityCheck(path);
|
||||||
|
return;
|
||||||
|
} else if (result == PortalHelperResult.RECHECK) {
|
||||||
|
this._client.check_connectivity_async(null, Lang.bind(this, function(client, result) {
|
||||||
|
try {
|
||||||
|
let state = client.check_connectivity_finish(result);
|
||||||
|
if (state >= NetworkManager.ConnectivityState.FULL)
|
||||||
|
this._closeConnectivityCheck(path);
|
||||||
|
} catch(e) { }
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
log('Invalid result from portal helper: ' + result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_syncConnectivity: function() {
|
||||||
|
if (this._mainConnection == null ||
|
||||||
|
this._mainConnection.state != NetworkManager.ActiveConnectionState.ACTIVATED) {
|
||||||
|
this._flushConnectivityQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isPortal = this._client.connectivity == NetworkManager.ConnectivityState.PORTAL;
|
||||||
|
// For testing, allow interpreting any value != FULL as PORTAL, because
|
||||||
|
// LIMITED (no upstream route after the default gateway) is easy to obtain
|
||||||
|
// with a tethered phone
|
||||||
|
// NONE is also possible, with a connection configured to force no default route
|
||||||
|
// (but in general we should only prompt a portal if we know there is a portal)
|
||||||
|
if (GLib.getenv('GNOME_SHELL_CONNECTIVITY_TEST') != null)
|
||||||
|
isPortal = isPortal || this._client.connectivity < NetworkManager.ConnectivityState.FULL;
|
||||||
|
if (!isPortal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let path = this._mainConnection.get_path();
|
||||||
|
for (let item of this._connectivityQueue) {
|
||||||
|
if (item == path)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let timestamp = global.get_current_time();
|
||||||
|
if (this._portalHelperProxy) {
|
||||||
|
this._portalHelperProxy.AuthenticateRemote(path, '', timestamp);
|
||||||
|
} else {
|
||||||
|
new PortalHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PortalHelper',
|
||||||
|
'/org/gnome/Shell/PortalHelper', Lang.bind(this, function (proxy, error) {
|
||||||
|
if (error) {
|
||||||
|
log('Error launching the portal helper: ' + error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._portalHelperProxy = proxy;
|
||||||
|
proxy.connectSignal('Done', Lang.bind(this, this._portalHelperDone));
|
||||||
|
|
||||||
|
proxy.AuthenticateRemote(path, '', timestamp);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._connectivityQueue.push(path);
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateIcon: function() {
|
_updateIcon: function() {
|
||||||
|
Loading…
Reference in New Issue
Block a user