Table of Contents

Gnome - Extensions - VPN Indicator

Displays if the system is connected to a VPN or not.


Create the directory for the extension

mkdir ~/.local/share/gnome-shell/extensions/vpn-indicator

Create a metadata.json file

metadata.json is a mandatory file of the extension, containing information about the extension such as its UUID, name and description.

metadata.json
{
  "description": "A VPN connection indicator.",
  "name": "VPN Indicator",
  "shell-version": [
    "3.32",
    "3.34",
    "3.36",
    "3.38",
    "40"
  ],
  "url": "",
  "uuid": "vpn-indicator",
  "version": 1
}

Create a extensions.js file

extensions.js is the core file of the extension and contains the function hooks init(), enable() and disable() used by GNOME Shell to load, enable and disable the extension.

extensions.js
const St = imports.gi.St;
const Main = imports.ui.main;
const Lang = imports.lang;
const Util = imports.misc.util;
const PanelMenu = imports.ui.panelMenu;
const Mainloop = imports.mainloop;
const GLib = imports.gi.GLib;
const Clutter = imports.gi.Clutter;
 
const VpnIndicator = new Lang.Class({
    Name: 'VpnIndicator',
    Extends: PanelMenu.Button,
 
    _init: function() {
        this.parent(0.0, "VPN Indicator", false);
 
        if (!this.buttonText) {
          this.buttonText = new St.Label({
              text: _("Loading..."),
              y_align: Clutter.ActorAlign.CENTER
          });
        }
 
        this.actor.add_actor(this.buttonText);
        this._refresh();
    },
 
    _checkVPN: function() {
        let [res, out, err, exit] = GLib.spawn_sync(null, ["/bin/bash", "-c","ip addr | grep tun0"], null, GLib.SpawnFlags.SEARCH_PATH, null);
 
        // To prevent /var/log/syslog filling with error messages once the object is destroyed.
        try {
            if (this.buttonText) {
              if (exit == 256)
                this.buttonText.set_text("VPN off");
              else if (exit == 0)
                this.buttonText.set_text("VPN on");
              else
                this.buttonText.set_text("VPN Error");
            }
        } catch (e) {
          //    logError(e, 'ExtensionError');
        }
 
        return exit;
    },
 
    _refresh: function() {
        var qres = this._checkVPN();
        //this._refreshUI(qres);
 
        // Calls the refresh function every 2 seconds.
        this._timeout = Mainloop.timeout_add_seconds(2, Lang.bind(this, this._refresh));
    },
 
    _refreshUI: function(data) {
/*      
        var text;
 
        if (data == 256) {
            text = "VPN is down!";
        } else if (data == 0) {
            text = "VPN is up!";
        } else {
            text = "Error!";
        }
 
        // To prevent /var/log/syslog filling with error messages once the object is destroyed.
        try {
            if (this.buttonText) {
                this.buttonText.set_text(text);
            }
        } catch (e) {
          //    logError(e, 'ExtensionError');
        }
 
*/
    }
});
 
 
let twMenu;
 
 
function init() {
}
 
function enable() {
    twMenu = new VpnIndicator;
    Main.panel.addToStatusArea('vpn-indicator', twMenu);
}
 
function disable() {
    if (this._timeout)
      Mainloop.source_remove(this._timeout);
 
    this._timeout = undefined;
 
    if (this.buttonText !== null) {
        this.buttonText.destroy();
        this.buttonText = null;
    }
 
    twMenu.destroy();
}

Reload GNOME to pick up the extension

Press Alt+F2, and enter r and press ENTER to restart GNOME Shell.


References

https://extensions.gnome.org/

http://smasue.github.io/gnome-shell-tw