Blame SOURCES/0001-objectManager-handle-proxies-coming-and-going.patch

f3cbb9
From 1fc22df08e365820fedccf92b95601859ce63f5b Mon Sep 17 00:00:00 2001
f3cbb9
From: Ray Strode <rstrode@redhat.com>
f3cbb9
Date: Fri, 7 Oct 2016 15:40:14 -0400
f3cbb9
Subject: [PATCH 1/2] objectManager: handle proxies coming and going
f3cbb9
f3cbb9
Ever since commit b8e29ae8c78658917c8a8ddd391667d7d9e36971
f3cbb9
(I think), start up is littered with this message:
f3cbb9
f3cbb9
 Gjs-WARNING **: JS ERROR: could not get remote objects for service
f3cbb9
 org.gnome.SettingsDaemon.Smartcard path
f3cbb9
f3cbb9
since gnome-shell is now started before gnome-settings-daemon.
f3cbb9
f3cbb9
This commit addresses the problem by making the object manager code
f3cbb9
not try to autostart its proxy, and instead wait for it to appear.
f3cbb9
f3cbb9
https://bugzilla.gnome.org/show_bug.cgi?id=772589
f3cbb9
---
f3cbb9
 js/misc/objectManager.js   | 34 ++++++++++++++++++++++++++++++++--
f3cbb9
 1 files changed, 34 insertions(+), 2 deletions(-)
f3cbb9
f3cbb9
diff --git a/js/misc/objectManager.js b/js/misc/objectManager.js
f3cbb9
index 225204347..5db7588b6 100644
f3cbb9
--- a/js/misc/objectManager.js
f3cbb9
+++ b/js/misc/objectManager.js
f3cbb9
@@ -19,101 +19,104 @@ const ObjectManagerIface = '<node> \
f3cbb9
   </signal> \
f3cbb9
   <signal name="InterfacesRemoved"> \
f3cbb9
     <arg name="objectPath" type="o"/> \
f3cbb9
     <arg name="interfaces" type="as" /> \
f3cbb9
   </signal> \
f3cbb9
 </interface> \
f3cbb9
 </node>';
f3cbb9
 
f3cbb9
 const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
f3cbb9
 
f3cbb9
 const ObjectManager = new Lang.Class({
f3cbb9
     Name: 'ObjectManager',
f3cbb9
     _init: function(params) {
f3cbb9
         params = Params.parse(params, { connection: null,
f3cbb9
                                         name: null,
f3cbb9
                                         objectPath: null,
f3cbb9
                                         knownInterfaces: null,
f3cbb9
                                         cancellable: null,
f3cbb9
                                         onLoaded: null });
f3cbb9
 
f3cbb9
         this._connection = params.connection;
f3cbb9
         this._serviceName = params.name;
f3cbb9
         this._managerPath = params.objectPath;
f3cbb9
         this._cancellable = params.cancellable;
f3cbb9
 
f3cbb9
         this._managerProxy = new Gio.DBusProxy({ g_connection: this._connection,
f3cbb9
                                                  g_interface_name: ObjectManagerInfo.name,
f3cbb9
                                                  g_interface_info: ObjectManagerInfo,
f3cbb9
                                                  g_name: this._serviceName,
f3cbb9
                                                  g_object_path: this._managerPath,
f3cbb9
-                                                 g_flags: Gio.DBusProxyFlags.NONE });
f3cbb9
+                                                 g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
f3cbb9
 
f3cbb9
         this._interfaceInfos = {};
f3cbb9
         this._objects = {};
f3cbb9
         this._interfaces = {};
f3cbb9
         this._onLoaded = params.onLoaded;
f3cbb9
 
f3cbb9
         if (params.knownInterfaces)
f3cbb9
             this._registerInterfaces(params.knownInterfaces);
f3cbb9
 
f3cbb9
         // Start out inhibiting load until at least the proxy
f3cbb9
         // manager is loaded and the remote objects are fetched
f3cbb9
         this._numLoadInhibitors = 1;
f3cbb9
         this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
f3cbb9
                                       this._cancellable,
f3cbb9
                                       Lang.bind(this, this._onManagerProxyLoaded));
f3cbb9
     },
f3cbb9
 
f3cbb9
     _tryToCompleteLoad: function() {
f3cbb9
+        if (this._numLoadInhibitors == 0)
f3cbb9
+            return;
f3cbb9
+
f3cbb9
         this._numLoadInhibitors--;
f3cbb9
         if (this._numLoadInhibitors == 0) {
f3cbb9
             if (this._onLoaded)
f3cbb9
                 this._onLoaded();
f3cbb9
         }
f3cbb9
     },
f3cbb9
 
f3cbb9
     _addInterface: function(objectPath, interfaceName, onFinished) {
f3cbb9
         let info = this._interfaceInfos[interfaceName];
f3cbb9
 
f3cbb9
         if (!info) {
f3cbb9
            if (onFinished)
f3cbb9
                onFinished();
f3cbb9
            return;
f3cbb9
         }
f3cbb9
 
f3cbb9
         let proxy = new Gio.DBusProxy({ g_connection: this._connection,
f3cbb9
                                        g_name: this._serviceName,
f3cbb9
                                        g_object_path: objectPath,
f3cbb9
                                        g_interface_name: interfaceName,
f3cbb9
                                        g_interface_info: info,
f3cbb9
-                                       g_flags: Gio.DBusProxyFlags.NONE });
f3cbb9
+                                       g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
f3cbb9
 
f3cbb9
         proxy.init_async(GLib.PRIORITY_DEFAULT,
f3cbb9
                          this._cancellable,
f3cbb9
                          Lang.bind(this, function(initable, result) {
f3cbb9
                let error = null;
f3cbb9
                try {
f3cbb9
                    initable.init_finish(result);
f3cbb9
                } catch(e) {
f3cbb9
                    logError(e, 'could not initialize proxy for interface ' + interfaceName);
f3cbb9
 
f3cbb9
                    if (onFinished)
f3cbb9
                        onFinished();
f3cbb9
                    return;
f3cbb9
                }
f3cbb9
 
f3cbb9
                let isNewObject;
f3cbb9
                if (!this._objects[objectPath]) {
f3cbb9
                    this._objects[objectPath] = {};
f3cbb9
                    isNewObject = true;
f3cbb9
                } else {
f3cbb9
                    isNewObject = false;
f3cbb9
                }
f3cbb9
 
f3cbb9
                this._objects[objectPath][interfaceName] = proxy;
f3cbb9
 
f3cbb9
                if (!this._interfaces[interfaceName])
f3cbb9
                    this._interfaces[interfaceName] = [];
f3cbb9
 
f3cbb9
                this._interfaces[interfaceName].push(proxy);
f3cbb9
 
f3cbb9
@@ -154,92 +157,119 @@ const ObjectManager = new Lang.Class({
f3cbb9
     },
f3cbb9
 
f3cbb9
     _onManagerProxyLoaded: function(initable, result) {
f3cbb9
         let error = null;
f3cbb9
         try {
f3cbb9
             initable.init_finish(result);
f3cbb9
         } catch(e) {
f3cbb9
             logError(e, 'could not initialize object manager for object ' + params.name);
f3cbb9
 
f3cbb9
             this._tryToCompleteLoad();
f3cbb9
             return;
f3cbb9
         }
f3cbb9
 
f3cbb9
         this._managerProxy.connectSignal('InterfacesAdded',
f3cbb9
                                          Lang.bind(this, function(objectManager, sender, [objectPath, interfaces]) {
f3cbb9
                                              let interfaceNames = Object.keys(interfaces);
f3cbb9
                                              for (let i = 0; i < interfaceNames.length; i++)
f3cbb9
                                                  this._addInterface(objectPath, interfaceNames[i]);
f3cbb9
                                          }));
f3cbb9
         this._managerProxy.connectSignal('InterfacesRemoved',
f3cbb9
                                          Lang.bind(this, function(objectManager, sender, [objectPath, interfaceNames]) {
f3cbb9
                                              for (let i = 0; i < interfaceNames.length; i++)
f3cbb9
                                                  this._removeInterface(objectPath, interfaceNames[i]);
f3cbb9
                                          }));
f3cbb9
 
f3cbb9
         if (Object.keys(this._interfaceInfos).length == 0) {
f3cbb9
             this._tryToCompleteLoad();
f3cbb9
             return;
f3cbb9
         }
f3cbb9
 
f3cbb9
+        this._managerProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
f3cbb9
+            if (this._managerProxy.g_name_owner)
f3cbb9
+                this._onNameAppeared();
f3cbb9
+            else
f3cbb9
+                this._onNameVanished();
f3cbb9
+        }));
f3cbb9
+
f3cbb9
+        if (this._managerProxy.g_name_owner)
f3cbb9
+            this._onNameAppeared();
f3cbb9
+    },
f3cbb9
+
f3cbb9
+    _onNameAppeared: function() {
f3cbb9
         this._managerProxy.GetManagedObjectsRemote(Lang.bind(this, function(result, error) {
f3cbb9
             if (!result) {
f3cbb9
                 if (error) {
f3cbb9
                    logError(error, 'could not get remote objects for service ' + this._serviceName + ' path ' + this._managerPath);
f3cbb9
                 }
f3cbb9
 
f3cbb9
                 this._tryToCompleteLoad();
f3cbb9
                 return;
f3cbb9
             }
f3cbb9
 
f3cbb9
             let [objects] = result;
f3cbb9
 
f3cbb9
             let objectPaths = Object.keys(objects);
f3cbb9
             for (let i = 0; i < objectPaths.length; i++) {
f3cbb9
                 let objectPath = objectPaths[i];
f3cbb9
                 let object = objects[objectPath];
f3cbb9
 
f3cbb9
                 let interfaceNames = Object.getOwnPropertyNames(object);
f3cbb9
                 for (let j = 0; j < interfaceNames.length; j++) {
f3cbb9
                     let interfaceName = interfaceNames[j];
f3cbb9
 
f3cbb9
                     // Prevent load from completing until the interface is loaded
f3cbb9
                     this._numLoadInhibitors++;
f3cbb9
                     this._addInterface(objectPath,
f3cbb9
                                        interfaceName,
f3cbb9
                                        Lang.bind(this, this._tryToCompleteLoad));
f3cbb9
                 }
f3cbb9
             }
f3cbb9
             this._tryToCompleteLoad();
f3cbb9
         }));
f3cbb9
     },
f3cbb9
 
f3cbb9
+    _onNameVanished: function() {
f3cbb9
+        let objectPaths = Object.keys(this._objects);
f3cbb9
+        for (let i = 0; i < objectPaths.length; i++) {
f3cbb9
+            let object = this._objects[objectPaths];
f3cbb9
+
f3cbb9
+            let interfaceNames = Object.keys(object);
f3cbb9
+            for (let j = 0; i < interfaceNames.length; i++) {
f3cbb9
+                let interfaceName = interfaceNames[i];
f3cbb9
+
f3cbb9
+                if (object[interfaceName])
f3cbb9
+                    this._removeInterface(objectPath, interfaceName);
f3cbb9
+            }
f3cbb9
+        }
f3cbb9
+    },
f3cbb9
+
f3cbb9
     _registerInterfaces: function(interfaces) {
f3cbb9
         for (let i = 0; i < interfaces.length; i++) {
f3cbb9
             let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);
f3cbb9
             this._interfaceInfos[info.name] = info;
f3cbb9
         }
f3cbb9
     },
f3cbb9
 
f3cbb9
     getProxy: function(objectPath, interfaceName) {
f3cbb9
         let object = this._objects[objectPath];
f3cbb9
 
f3cbb9
         if (!object)
f3cbb9
             return null;
f3cbb9
 
f3cbb9
         return object[interfaceName];
f3cbb9
     },
f3cbb9
 
f3cbb9
     getProxiesForInterface: function(interfaceName) {
f3cbb9
         let proxyList = this._interfaces[interfaceName];
f3cbb9
 
f3cbb9
         if (!proxyList)
f3cbb9
             return [];
f3cbb9
 
f3cbb9
         return proxyList;
f3cbb9
     },
f3cbb9
 
f3cbb9
     getAllProxies: function() {
f3cbb9
         let proxies = [];
f3cbb9
 
f3cbb9
         let objectPaths = Object.keys(this._objects);
f3cbb9
         for (let i = 0; i < objectPaths.length; i++) {