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