Unable to get CloudProviders signals from DBus

Hello everyone,

I’m trying to use the libcloudproviders DBus API in a shell extension I’m writing.

However, I can’t get signals from DBus. Specifically, the InterfacesAdded and InterfacesRemoved signals from the ObjectManager interface (which should be emitted when a provider or an account is added or removed) and the g-properties-changed signal on accounts objects (which should be emitted when the status of an account changes).

To test this, I’m using the Nextcloud client, and adding/removing folder syncs (that should send the InterfacesAdded and InterfacesRemoved signals) and putting/deleting files in these folders (that should send the g-properties-changed signal). I can see the values changing in D-Feet, but can’t get any signal.

Here’s my code for the ObjectManager:

const { Gio } = imports.gi;

const OBJECT_MANAGER_INTERFACE = `
<node>
    <interface name="org.freedesktop.DBus.ObjectManager">
        <method name="GetManagedObjects">
            <arg type="a{oa{sa{sv}}}" name="object_paths_interfaces_and_properties" direction="out"/>
        </method>
        <signal name="InterfacesAdded">
            <arg type="o" name="object_path"/>
            <arg type="a{sa{sv}}" name="interfaces_and_properties"/>
        </signal>
        <signal name="InterfacesRemoved">
            <arg type="o" name="object_path"/>
            <arg type="as" name="interfaces"/>
        </signal>
    </interface>
</node>`;

function enable() {
    const ObjectManagerProxy = Gio.DBusProxy.makeProxyWrapper(OBJECT_MANAGER_INTERFACE);
    const objectManagerProxy = new ObjectManagerProxy(
        Gio.DBus.session,
        'com.nextcloudgmbh.Nextcloud',
        '/com/nextcloudgmbh/Nextcloud'
    );
    objectManagerProxy.connectSignal('InterfacesAdded', () => log('Interfaces added'));
    objectManagerProxy.connectSignal('InterfacesRemoved', () => log('Interfaces removed'));
}

And the one for listening to an account:

const { Gio } = imports.gi;

const CLOUDPROVIDERS_ACCOUNT_INTERFACE = `
<node>
    <interface name="org.freedesktop.CloudProviders.Account">
        <property type="s" name="Name" access="read"/>
        <property type="s" name="Path" access="read"/>
        <property type="s" name="Icon" access="read"/>
        <property type="i" name="Status" access="read"/>
        <property type="s" name="StatusDetails" access="read"/>
    </interface>
</node>`;

function enable() {
    const AccountProxy = Gio.DBusProxy.makeProxyWrapper(CLOUDPROVIDERS_ACCOUNT_INTERFACE);
    const accountProxy = new AccountProxy(
        Gio.DBus.session,
        'com.nextcloudgmbh.Nextcloud',
        '/com/nextcloudgmbh/Nextcloud/Folder/0'
    );
    accountProxy.connect('g-properties-changed', () => log('Properties changed'));
}

I tried this on other DBus interfaces, and I get signals. Is there anything I’m missing here? Or do you think it is something not happening in libcloudproviders?

Probably not the cause of your problems but gio does actually have Gio.DBusObjectManagerClient

Thank you, I tried listening to all the implemented signals on Gio.DBusObjectManagerClient with the following code:

const { Gio } = imports.gi;

function enable() {
    const client = Gio.DBusObjectManagerClient.new_sync(
        Gio.DBus.session,
        Gio.DBusObjectManagerClientFlags.NONE,
        'com.nextcloudgmbh.Nextcloud',
        '/com/nextcloudgmbh/Nextcloud',
        null,
        null
    );
    client.connect('interface-added', () => log('interface-added'));
    client.connect('interface-removed', () => log('interface-removed'));
    client.connect('object-added', () => log('object-added'));
    client.connect('object-removed', () => log('object-removed'));
    client.connect('interface-proxy-properties-changed', () => log('interface-proxy-properties-changed'));
    client.connect('interface-proxy-signal', () => log('interface-proxy-signal'));
}

But again nothing seems to be emitted when adding or removing folder syncs.

What’s strange is that when I close and open the session, the interface-proxy-properties-changed and g-properties-changed are each emitted twice, but after that nothing is emitted even if I can see things changing in D-Feet.

After some fiddling I managed to get signals with a very strange change: I need to initialize the variable storing the proxy globally.

let accountProxy;
function enable() {
    const AccountProxy = Gio.DBusProxy.makeProxyWrapper(CLOUDPROVIDERS_ACCOUNT_INTERFACE);
    accountProxy = new AccountProxy(
        Gio.DBus.session,
        'com.nextcloudgmbh.Nextcloud',
        '/com/nextcloudgmbh/Nextcloud/Folder/0'
    );
    accountProxy.connect('g-properties-changed', () => log('Properties changed'));
}

I then get all the signals. But if I initialize the variable just before creating the proxy (inside the enable function), I get some signals but it also misses others. And if I initialize the variable with the proxy, I don’t get anything.

I really have no clue about what’s causing this behavior, is this expected?

In your code samples above the proxy is being garbage collected when the function enable() returns, since the variable is in the function’s scope.

Thank you, that would be the explanation!

I guess that with the other proxies that seemed to work without storing them globally, I had simply been lucky and managed to get signals before they were garbage collected?

More likely you were holding a reference elsewhere, or the signals were emitted as a result of something synchronous and thus the callbacks were invoked before the function returned.

There is a short guide called Tips on Memory Management in the GNOME Wiki that covers some of the basics that related to GJS and GObjects.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.