File gnome-shell-domain.patch of Package gnome-shell

Index: gnome-shell-3.26.0/js/gdm/domain.js
===================================================================
--- /dev/null
+++ gnome-shell-3.26.0/js/gdm/domain.js
@@ -0,0 +1,243 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+/*
+ * Copyright 2011 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+const Atk = imports.gi.Atk;
+const Clutter = imports.gi.Clutter;
+const Gdm = imports.gi.Gdm;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+const Signals = imports.signals;
+const St = imports.gi.St;
+
+const Main = imports.ui.main;
+const PopupMenu = imports.ui.popupMenu;
+
+const DomainLoadStatus = {
+    INIT : 0,
+    SEPARATOR : 1,
+    OWN_DOMAIN : 2,
+    TRUSTED_DOMAINS : 3,
+    DONE : 4,
+    ERR : 5
+};
+
+var DomainMenuButton = new Lang.Class({
+    Name: 'DomainMenuButton',
+
+    _init: function () {
+        this._separator = null;
+        this.domain_enabled = false;
+        this._domains = new Array();
+        this._load_config();
+    },
+
+
+    _domainsPush: function(domain) {
+        let valid_content = domain.replace(/\s+/g, '');
+
+        if (valid_content.length > 0) {
+            if (this._domains.indexOf(valid_content) == -1)
+                this._domains.push (valid_content);
+        }
+    },
+
+    _generate: function() {
+        let gearIcon = new St.Icon({ icon_name: 'samba-window',
+                                  icon_size: 24
+                                 });
+        this._button = new St.Button({ style_class: 'login-dialog-session-list-button', //FIXME
+                                       reactive: true,
+                                       track_hover: true,
+                                       can_focus: true,
+                                       accessible_name: _("Choose Domain"),
+                                       accessible_role: Atk.Role.MENU,
+                                       child: gearIcon });
+
+        gearIcon.show();
+        this.actor = new St.Bin({ child: this._button });
+
+        this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP);
+        Main.uiGroup.add_actor(this._menu.actor);
+        this._menu.actor.hide();
+
+        this._menu.connect('open-state-changed',
+                           Lang.bind(this, function(menu, isOpen) {
+                                if (isOpen)
+                                    this._button.add_style_pseudo_class('active');
+                                else
+                                    this._button.remove_style_pseudo_class('active');
+                           }));
+
+        this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
+        this._manager.addMenu(this._menu);
+
+        this._button.connect('clicked', Lang.bind(this, function() {
+            this._menu.toggle();
+        }));
+
+        this._populate();
+    },
+
+    _load_config: function() {
+        let keyfile = new GLib.KeyFile();
+        let path = "/etc/gdm/custom.conf";
+        let domain_group = "domains";
+
+    //? Why must use 'try'
+        try {
+            keyfile.load_from_file(path, GLib.KeyFileFlags.NONE);
+        } catch(e) {
+        }
+
+        if (!keyfile.has_group(domain_group)) {
+            return;
+    }
+
+        this.domain_enabled = keyfile.get_boolean(domain_group, 'Enable');
+        if (this.domain_enabled) {
+            let content = keyfile.get_string(domain_group, 'Domains');
+        let domains = content.split(';');
+        for (let i = 0; i < domains.length; i++) {
+        this._domainsPush(domains[i]);
+        }
+        this._generate();
+    }
+    },
+
+    _readStdout: function(data) {
+        this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(stream, result) {
+            let [line, len] = this._dataStdout.read_line_finish_utf8(result);
+
+            if (line == null) {
+                // end of file
+                this._stdout.close(null);
+        this.loadDomains(data, null);
+                return;
+            }
+
+        data.push(line);
+            this._readStdout(data);
+        }));
+    },
+
+    loadCommand: function(argv) {
+        try {
+            let data = new Array();
+            let [success, pid, stdin, stdout, stderr] = GLib.spawn_async_with_pipes(null,
+                    argv,
+                    null,
+                    GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
+                    null);
+            this._stdout = new Gio.UnixInputStream({ fd: stdout, close_fd: true });
+            GLib.close(stdin);
+            GLib.close(stderr);
+            this._dataStdout = new Gio.DataInputStream({ base_stream: this._stdout });
+            this._readStdout(data);
+        } catch (e) {
+            this.loadDomains(null, e);
+    }
+    },
+
+    loadDomains: function(data, err) {
+    /*FIXME: reload every 5 minutes? */
+    /*TODO: load the setting file */
+        switch (this._status) {
+            case DomainLoadStatus.INIT:
+                this._status = DomainLoadStatus.SEPARATOR;
+                this.loadCommand(["wbinfo", "--separator"]);
+                break;
+            case DomainLoadStatus.SEPARATOR:
+                if (data) {
+                    this._separator = data[0];
+                    this._status = DomainLoadStatus.OWN_DOMAIN;
+                    this.loadCommand(["wbinfo", "--own-domain"]);
+                } else {
+                    this._status = DomainLoadStatus.ERR;
+                    this._menu.removeAll();
+                    item = new PopupMenu.PopupMenuItem(_("Cannot receive 'separator'"));
+                    item.setSensitive(false);
+                    this._menu.addMenuItem(item);
+                }
+                break;
+            case DomainLoadStatus.OWN_DOMAIN:
+                if (data) {
+                    for (let i = 0; i < data.length; i++) {
+                        this._domainsPush(data[i]);
+                    }
+                }
+                this._status = DomainLoadStatus.TRUSTED_DOMAINS;
+                this.loadCommand(["wbinfo", "--trusted-domains"]);
+                break;
+            case DomainLoadStatus.TRUSTED_DOMAINS:
+                if (data) {
+                    for (let i = 0; i < data.length; i++) {
+                        this._domainsPush(data[i]);
+                    }
+                }
+                this._status = DomainLoadStatus.DONE;
+                this._menu.removeAll();
+                for (let i = 0; i < this._domains.length; i++) {
+                    item = new PopupMenu.PopupMenuItem(this._domains[i]);
+                        this._menu.addMenuItem(item);
+                        item.connect('activate', Lang.bind(this, function(item) {
+                        //?? Why it does not work
+                        //this.setActiveDomain(this._domains[i]);
+                        this.setActiveDomain(item.label.text);
+                    }));
+                }
+                break;
+    }
+    },
+
+    _populate: function() {
+        //TODO Recent domains?
+        item = new PopupMenu.PopupMenuItem(_("loading the wbinfos..."));
+        item.setSensitive(false);
+        this._menu.addMenuItem(item);
+        this._status = DomainLoadStatus.INIT;
+        this.loadDomains(null, null);
+    },
+
+    setActiveDomain: function(domain) {
+        this._activeDomain = domain;
+        //this.emit('domain-activated', this._activeDomain);
+        this.emit('domain-activated');
+    },
+
+    getActiveDomain: function(domain) {
+        return this._activeDomain;
+    },
+
+    getQuestionMessage: function() {
+        return _("User for ") + this._activeDomain;
+    },
+
+    getHintMessage: function() {
+        return _("Contact dliang to get help");
+    },
+
+    getDomainUser: function(user) {
+        return this._activeDomain + this._separator + user;
+    }
+});
+Signals.addSignalMethods(DomainMenuButton.prototype);
Index: gnome-shell-3.26.0/js/gdm/loginDialog.js
===================================================================
--- gnome-shell-3.26.0.orig/js/gdm/loginDialog.js
+++ gnome-shell-3.26.0/js/gdm/loginDialog.js
@@ -33,6 +33,7 @@ const Signals = imports.signals;
 const St = imports.gi.St;
 
 const AuthPrompt = imports.gdm.authPrompt;
+const Domain = imports.gdm.domain;
 const Batch = imports.gdm.batch;
 const BoxPointer = imports.ui.boxpointer;
 const CtrlAltTab = imports.ui.ctrlAltTab;
@@ -452,6 +453,14 @@ var LoginDialog = new Lang.Class({
         this._authPrompt.hide();
         this.actor.add_child(this._authPrompt.actor);
 
+        this._userLayout = new St.BoxLayout({ vertical: false,
+                        x_expand: true
+                       });
+        this._userSelectionBox.add(this._userLayout,
+                                   { expand: true,
+                                     x_align: St.Align.START,
+                                     x_fill: true });
+
         // translators: this message is shown below the user list on the
         // login screen. It can be activated to reveal an entry for
         // manually entering the username.
@@ -469,10 +478,24 @@ var LoginDialog = new Lang.Class({
 
         this._notListedButton.hide();
 
-        this._userSelectionBox.add(this._notListedButton,
+        this._userLayout.add(this._notListedButton,
+                                   { expand: false});
+
+        // we add domain menu button
+        this._domainMenuButton = new Domain.DomainMenuButton();
+        if (this._domainMenuButton.domain_enabled) {
+            this._domainMenuButton.actor.hide();
+
+            this._domainMenuButton.connect('domain-activated',
+                                  Lang.bind(this, function(list) {
+                        this._hideUserListAskForDomainUsernameAndBeginVerification();
+                                            }));
+            this._userLayout.add(this._domainMenuButton.actor,
                                    { expand: false,
-                                     x_align: St.Align.START,
+                                     x_align: St.Align.END,
                                      x_fill: true });
+        }
+        // domain end
 
         this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
                                                opacity: 0,
@@ -948,6 +971,37 @@ var LoginDialog = new Lang.Class({
             }));
     },
 
+    _askForDomainUsernameAndBeginVerification: function(domain) {
+        this._authPrompt.setPasswordChar('');
+        this._authPrompt.setQuestion(this._domainMenuButton.getQuestionMessage());
+
+        //FIXME: I sugguest to add this info for customer to contact their account manager
+        this._authPrompt.setMessage(this._domainMenuButton.getHintMessage(), GdmUtil.MessageType.HINT);
+
+        let realmManager = new Realmd.Manager();
+        let realmSignalId = realmManager.connect('login-format-changed',
+                                                 Lang.bind(this, this._showRealmLoginHint));
+        this._showRealmLoginHint(realmManager.loginFormat);
+
+        let nextSignalId = this._authPrompt.connect('next',
+                                                    Lang.bind(this, function() {
+                                                        this._authPrompt.disconnect(nextSignalId);
+                                                        this._authPrompt.updateSensitivity(false);
+                                                        let answer = this._authPrompt.getAnswer();
+                            let domain_answer = this._domainMenuButton.getDomainUser(answer);
+                                                        this._user = this._userManager.get_user(domain_answer);
+                                                        this._authPrompt.clear();
+                                                        this._authPrompt.startSpinning();
+                                                        this._authPrompt.begin({ userName: domain_answer});
+                                                        this._updateCancelButton();
+
+                                                        realmManager.disconnect(realmSignalId)
+                                                        realmManager.release();
+                                                    }));
+        this._updateCancelButton();
+        this._showPrompt();
+    },
+
     _startSession: function(serviceName) {
         Tweener.addTween(this.actor,
                          { opacity: 0,
@@ -1116,6 +1170,11 @@ var LoginDialog = new Lang.Class({
         this._askForUsernameAndBeginVerification();
     },
 
+    _hideUserListAskForDomainUsernameAndBeginVerification: function() {
+        this._hideUserList();
+        this._askForDomainUsernameAndBeginVerification();
+    },
+
     _hideUserListAndBeginVerification: function() {
         this._hideUserList();
         this._authPrompt.begin();
@@ -1128,6 +1187,9 @@ var LoginDialog = new Lang.Class({
         this._sessionMenuButton.close();
         this._setUserListExpanded(true);
         this._notListedButton.show();
+        if (this._domainMenuButton.domain_enabled)
+            this._domainMenuButton.actor.show();
+        this._userLayout.show();
         if (!Main.screenShield.locked)
             this._userList.actor.grab_key_focus();
     },
Index: gnome-shell-3.26.0/po/POTFILES.in
===================================================================
--- gnome-shell-3.26.0.orig/po/POTFILES.in
+++ gnome-shell-3.26.0/po/POTFILES.in
@@ -7,6 +7,7 @@ data/org.gnome.shell.gschema.xml.in
 data/org.gnome.Shell.PortalHelper.desktop.in.in
 js/extensionPrefs/main.js
 js/gdm/authPrompt.js
+js/gdm/domain.js
 js/gdm/loginDialog.js
 js/gdm/util.js
 js/misc/systemActions.js
Index: gnome-shell-3.26.0/js/js-resources.gresource.xml
===================================================================
--- gnome-shell-3.26.0.orig/js/js-resources.gresource.xml
+++ gnome-shell-3.26.0/js/js-resources.gresource.xml
@@ -2,6 +2,7 @@
 <gresources>
   <gresource prefix="/org/gnome/shell">
     <file>gdm/authPrompt.js</file>
+    <file>gdm/domain.js</file>
     <file>gdm/batch.js</file>
     <file>gdm/fingerprint.js</file>
     <file>gdm/loginDialog.js</file>